Scripting Language

An AutoHotkey script is basically a set of instructions for the program to follow, written in a custom language exclusive to AutoHotkey. This language bears some similarities to several other scripting languages, but also has its own unique strengths and pitfalls. This
document describes the language and also tries to point out common pitfalls.

See Concepts and Conventions for more general explanation of various concepts utilised by AutoHotkey.
There are two distinct styles of syntax used in AutoHotkey: legacy syntax and expressions.

Table of Contents

General Conventions
Comments
Expressions

Strings / Text
Variables

Operators

Function Calls
Operators for Objects
Expression Statements

Legacy Syntax
Commands

OutputVar and InputVar Parameters
Text Parameters

Numeric Parameters

% Expression

Documentation Conventions
Optional Parameters

Expressions vs Legacy Syntax
Different Equals

Commands vs Functions
Control Flow Statements

Control Flow vs Commands
If Statement

Loop Statement

Not Control Flow

Structure of a Script
Auto-execute Section

Subroutines
User-Defined Functions
#Include

Miscellaneous

Dynamic Variables

Pseudo-arrays

Associative pseudo-arrays

Commands which create pseudo-arrays

Labels

General Conventions

Names: Variable and function names are not case sensitive (for example, CurrentDate is the same as currentdate). For details such as maximum length and usable characters, see Names.

No typed variables: Variables have no explicitly defined type; instead, a value of any type can be stored in any variable (excluding
built-in variables). Numbers may be automatically converted to strings (text) and vice versa, depending on the situation.

Declarations are optional: Except where noted on the functions page, variables do not need to be declared; they come into existence
simply by using them (and each variable starts off empty/blank).

Spaces are mostly ignored: Indentation (leading space) is important for writing readable code, but is not required by the program and is generally ignored. Spaces and tabs are generally ignored at the end of a line, within an expression (except between quotes), and before
and after command parameters. However, spaces are significant in some cases, including:

Function and method calls require there to be no space between the function/method name and (.
Spaces are required when performing concatenation.

Spaces may be required between two operators, to remove ambiguity.


Single-line comments require a leading space if they are not at the start of the line.

Line breaks are meaningful: Line breaks generally act as a statement separator, terminating the previous command or expression. (A

statement is simply the smallest standalone element of the language that expresses some action to be carried out.) The exception to this is line continuation (see below).

Line continuation: Long lines can be divided up into a collection of smaller ones to improve readability and maintainability. This is
achieved by preprocessing, so is not part of the language as such. There are two methods:

Line continuation, where lines that begin with an expression operator (except ++ and --) are merged with the previous line. Lines
are merged regardless of whether the line actually contains an expression.

Continuation sections, where multiple lines are merged with the line above the section. The start and end of a continuation section
are marked with ( and ) (both symbols must appear at the beginning of a line, excluding whitespace).

Comments

Comments are portions of text within the script which are ignored by the program. They are typically used to add explanation or disable parts of the code.

Scripts can be commented by using a semicolon at the beginning of a line. For example:

; This entire line is a comment.

Comments may also be added at the end of a line, in which case the semicolon must have at least one space or tab to its left. For
example:

Run Notepad  ; This is a comment on the same line as a command.

In addition, the /* and */ symbols can be used to comment out an entire section, but only if the symbols appear at the beginning of a line as in this example:

/*

MsgBox, This line is commented out (disabled).

MsgBox, Common mistake: */ this does not end the comment.
MsgBox, This line is commented out. 

*/

Since comments are ignored when a script is launched, they do not impact performance or memory utilization.
The default comment character (semicolon) can be changed to some other character or string via #CommentFlag.
Expressions

Expressions are combinations of one or more values, variables, operators and function calls. For example, 10, 1+1 and MyVar are valid
expressions. Usually, an expression takes one or more values as input, performs one or more operations, and produces a value as the
result. The process of finding out the value of an expression is called evaluation. For example, the expression 1+1 evaluates to the
number 2.

Commands are designed to take a list of parameters and perform only a single action per line, whereas simple expressions can be pieced together to form increasingly more complex expressions. For example, if Discount/100 converts a discount percentage to a fraction, 1 - Discount/100 calculates a fraction representing the remaining amount, and Price * (1 - Discount/100) applies it to produce the net price.

Values are numbers, objects or strings. A literal value is one written physically in the script; one that you can see when you look at the
code.

Strings / Text

For a more general explanation of strings, see Strings.

A string, or string of characters, is just a text value. In an expression, literal text must be enclosed in quotation marks to differentiate it
from a variable name or some other expression. This is often referred to as a quoted literal string, or just quoted string. For example,
"This is a quoted string.".

To include an actual quote character inside a quoted string, specify two consecutive quotes as shown twice in this example: "She said, ""An apple a day.""".

Quoted strings can contain escape sequences such as `t (tab), `n (linefeed), and `r (carriage return). Unlike unquoted text, it is not
necessary to escape commas or percent signs, as quoted strings cannot contain variables. The use of the `" escape sequence to produce a literal quote-character is currently not supported; instead, use two consecutive quotes as shown above.


Variables

For a basic explanation and general details about variables, see Variables.

Variables can be used in an expression simply by writing the variable's name. For example, A_ScreenWidth/2. However, variables
cannot be used inside a quoted string. Instead, variables and other values can be combined with text through a process called
concatenation. There are two ways to concatenate values in an expression:

Implicit concatenation: "The value is " MyVar
Explicit concatenation: "The value is " . MyVar

Implicit concatenation is also known as auto-concat. In both cases, the spaces preceding the variable and dot are mandatory.
The Format function can also be used for this purpose. For example:

MsgBox % Format("You are using AutoHotkey v{1} {2}-bit.", A_AhkVersion, A_PtrSize*8)

To assign a value to a variable, use the := assignment operator, as in MyVar := "Some text".

Percent signs within an expression are used to create dynamic variable references and dynamic function calls. Most of the time these
constructs are not needed, so in general, variable names should not be enclosed in percent signs within an expression.

Operators

Operators take the form of a symbol or group of symbols such as + or :=, or one of the words and, or, not or new. They take one, two or three values as input and return a value as the result. A value or sub-expression used as input for an operator is called an operand.

Unary operators are written either before or after a single operand, depending on the operator. For example, -x or not keyIsDown.
Binary operators are written in between their two operands. For example, 1+1 or 2 * 5.

AutoHotkey has only one ternary operator, which takes the form condition ? valueIfTrue : valueIfFalse.

Some unary and binary operators share the same symbols, in which case the meaning of the operator depends on whether it is written
before, after or in between two values. For example, x-y performs subtraction while -x inverts the sign of x (producing a positive value from a negative value and vice versa).

Operators of equal precedence such as multiply (*) and divide (/) are evaluated in left-to-right order unless otherwise specified in the
operator table. By contrast, an operator of lower precedence such as add (+) is evaluated after a higher one such as multiply (*). For
example, 3 + 2 * 2 is evaluated as 3 + (2 * 2). Parentheses may be used to override precedence as in this example: (3 + 2) * 2

Function Calls

For a general explanation of functions and related terminology, see Functions/Commands.

Functions take a varying number of inputs, perform some action or calculation, and then return a result. The inputs of a function are
called parameters or arguments. A function is called simply by writing its name followed by its parameters enclosed in parentheses. For example, GetKeyState("Shift") returns (evaluates to) 1 if the Shift key is being held down or 0 otherwise.

Note: There must not be any space between the function name and open parenthesis.

When compared to commands, the requirement for parentheses may seem cryptic or verbose at first, but they are what allows a function call to be combined with other operations. For example, the expression GetKeyState("Shift", "P") and GetKeyState("Ctrl", "P") returns 1 only if both keys are being physically held down.

Function names are always global, and are separate to variable names. For example, Round can be both a variable name and a function
name, and Round := 1 will not affect Round(n) in any way.

Operators for Objects

There are other symbols used in expressions which don't quite fit into any of the categories defined above, or that affect the meaning of
other parts of the expression, as described below. These all relate to objects in some way. Providing a full explanation of what each
construct does would require introducing more concepts which are outside the scope of this section.

Alpha.Beta is often called member access. Alpha is an ordinary variable, and could be replaced with a function call or some other sub- expression which returns an object. When evaluated, the object is sent a request "give me the value of property Beta", "store this value in property Beta" or "call the method named Beta". In other words, Beta is a name which has meaning to the object; it is not a local or
global variable.

Alpha.Beta() is a method call, as described above.

Alpha.Beta[Param] is a specialised form of member access which includes additional parameters in the request. While Beta is a simple name, Param is an ordinary variable or sub-expression, or a list of sub-expressions separated by commas (the same as in a function's


parameter list).

Alpha[Index] has a similar function to Alpha.Beta, but each part is interpreted in a more standard way. That is, both Alpha and Index
are variables in this case, and could be replaced with virtually any sub-expression. This syntax is usually used to retrieve an element of
an array or associative array.

new ClassName() is used to instantiate a class, or create an object derived from another object. Although this looks like a function call, ClassName is actually an ordinary variable. Similarly, new Alpha.Beta() would create an object derived from the object returned by
Alpha.Beta; Beta is neither a function nor a method. If the optional parentheses are present, they may contain parameters for the object's __New method.

[A, B, C] creates an array with the initial contents A, B and C (all variables in this case), where A is element 1.

{Key1: Value1, Key2: Value2} creates an associative array from a list of key-value pairs. A value can later be retrieved by its
associated key. Writing a plain word (consisting of alphanumeric characters, underscore and non-ASCII characters) to the left of : is
equivalent to enclosing that word in quotation marks. For example, {A: B} is equivalent to {"A": B}. However, {(A): B} uses the
contents of the variable A as the key.

MyFunc(Params*) is a variadic function call. The asterisk must immediately precede the closing parenthesis at the end of the function's
parameter list. Params must be a variable or sub-expression which returns an array object. Although it isn't valid to use Params* just
anywhere, it can be used in an array literal ([A, B, C, ArrayToAppend*]) or indexer (Alpha[Params*]).

Expression Statements

Not all expressions can be used alone on a line. For example, a line consisting of just 21*2 or "Some text" wouldn't make any sense. An expression statement is an expression used on its own, typically for its side-effects. Most expressions with side-effects can be used this
way, so it is generally not necessary to memorise the details of this section.

The following types of expressions can be used as statements:

Assignments, as in x := y, compound assignments such as x += y, and increment/decrement operators such as ++x and x--. However, in AutoHotkey v1, ++, --, +=, -=, *= and /= have slightly different behavior when used alone on a line, as they are actually equivalent to EnvAdd, EnvSub, EnvMult or EnvDiv. For details, see "Known limitations" under Assign in the table of operators.

Function calls such as MyFunc(Params). However, a standalone function call cannot be followed by an open brace { (at the end of the
line or on the next line), because it would be confused with a function declaration.

Method calls such as MyObj.MyMethod().

Member access using square brackets, such as MyObj[Index], which can have side-effects like a function call.

Expressions starting with the new operator, as in new ClassName, because sometimes a class can be instantiated just for its side-effects.
Ternary expressions such as x ? CallIfTrue() : CallIfFalse(). However, in AutoHotkey v1, command names take precedence. For example, MsgBox ? 1 : 0 shows a message box.

Expressions starting with (. However, there usually must be a matching ) on the same line, otherwise the line would be interpreted as the start of a continuation section.

Expressions that start with any of those described above (but not those described below) are also allowed, for simplicity. For example,
MyFunc()+1 is currently allowed, although the +1 has no effect and its result is discarded. Such expressions might become invalid in the future due to enhanced error-checking.

Member access using a dot (once or in a series), such as ExcelApp.Quit or x.y.z. However, unless parentheses are used (as in a method call), this cannot be the prefix of a larger expression. For example, ExcelApp.Quit, xxx is prohibited due to the apparent similarity to
command syntax.

Legacy Syntax

Legacy or command syntax generally only allows a single action per line, but uses fewer characters to perform simple tasks such as
sending keystrokes or running a program. The syntax consists of command and variable names, unquoted text and a few symbols such as ,, = and %.

Unquoted text is simply text, not enclosed in quote marks, just straight up. Since the text has no explicit start and end marks, it ends at
the end of the line or the end of the parameter. Leading and trailing spaces and tabs are ignored. Within unquoted text, the following
characters have special meaning:

%: Enclose a variable name in percent signs to include the contents of that variable. For example, The year is %A_Year%.

Note: Variable names are not always enclosed in percent signs; they are required only within unquoted text. Percent signs should
not be used anywhere else, except to create a dynamic variable reference or dynamic function call.


Note: Only a plain variable name can be used. Array elements, properties and other expressions are not supported.

,: Comma is used to delimit (separate) the parameters of a command, with some exceptions. It has no special meaning when used
in an assignment or comparison, so is interpreted literally in such cases.

`: An escape character is usually used to indicate that the character immediately following it should be interpreted differently than
it normally would. For example, `% produces a literal percent sign and `, produces a literal comma. Some other common escape
sequences produce special characters, such as `t (tab), `n (linefeed), and `r (carriage return).

Commands accept a mixture of unquoted text, variable names and numeric expressions.

Send, The time is %A_Hour% o'clock.

Legacy assignment assigns unquoted text to a variable.

Clipboard = This text is copied to the clipboard.

If statements perform an action only if the specified condition is met.

If Var = Text value

There are also several other control flow statements (such as loops) which use legacy syntax similar to commands.
Commands

A command is an instruction to carry out a specific predefined action. "Command" may also refer to a specific predefined action, such as MsgBox. The set of available commands is predefined and cannot be changed by the script.

A command is called simply by writing its name at the beginning of a line, optionally followed by parameters. For example:

MsgBox, The time is %A_Hour% o'clock.

The comma separating the command name from its parameters is optional, except in the following cases:

When it's necessary to prevent the line from being interpreted as a legacy assignment or assignment expression.

MsgBox, := This would be an assignment without the comma.
When the first parameter is blank.

MsgBox,, Second, Third

When the command is alone at the top of a continuation section.

Each parameter of a command may accept different syntax, depending on the command. There are four types of parameters:
OutputVar

InputVar
Text
Number

In most cases the percent prefix can be used to pass an expression.
OutputVar and InputVar Parameters

OutputVar and InputVar parameters require a variable name or dynamic variable reference. For example:

; Replace all spaces with pluses:

StringReplace, NewStr, OldStr, %A_Space%, +, All

This command reads the value from OldStr (the InputVar) and stores the result in NewStr (the OutputVar).

Note: Only a plain variable can be used as an OutputVar. Array elements, properties and other expressions are not supported.
InputVar parameters can accept an expression only when the percent prefix is used. However, the prefix is not supported in the Var
parameters of legacy If commands, so If (expression) should be used instead.

Text Parameters

Text parameters accept unquoted text. For example:

MsgBox, The time is %A_Hour% o'clock.

Since commas and percent signs have special meaning, use the escape sequence `, to specify a literal comma and `% to specify a literal


percent sign. For clarity, it is best to always escape any comma which is intended to be literal, but escaping comma is optional in the
following cases:

In the last parameter of any command.

In the Text parameter of MsgBox, which has smart comma handling.

To include a leading or trailing space or tab, use the built-in variables %A_Space% and %A_Tab% or a forced expression such as % " x ". [v1.1.06+]: Whitespace can also be preserved by preceding the space or tab with an escape character, except for whitespace at the end of a line.

Text parameters can also accept a forced expression.
Numeric Parameters

Numeric parameters accept a literal number or an expression, and can be identified by phrasing like "This parameter can be an
expression."

For historical reasons, simple variable references alone or combined with digits are not interpreted as expressions. For example:

Sleep %n%000  ; Sleep for n seconds.
Sleep %m%     ; Sleep for m milliseconds.

To perform a double-deref in such cases, enclose the expression in parentheses: Sleep (%m%)

Note that mixed-type parameters such as SetTimer's second parameter, which sometimes accepts a number and sometimes accepts a
string such as On or Off, are actually Text parameters, and as such, they do not accept expressions unless the percent prefix is used.

Numeric parameters allow and ignore the percent prefix.
% Expression

Although purely numeric parameters accept an expression by default, all other parameters of commands do not. Specify a percent sign
followed by a space or tab to force a parameter to accept an expression. For example, all of the following are effectively identical
because Sleep's first parameter is expression-capable:

Sleep MillisecondsToWait
Sleep %MillisecondsToWait%
Sleep % MillisecondsToWait

Note: Using the percent-space prefix in a numeric parameter does not necessarily force it to be an expression.
All parameters support the percent-space prefix except for:

The Var parameter of any legacy If command. Users can avoid confusion by always using if (expression).
OutputVar parameters, which accept a variable reference using the same syntax as expressions.

Some users may find it easier to always force an expression, keeping to one consistent syntax (expression syntax) as much as possible.
Documentation Conventions

At the top of each page which documents a command, there is usually a block showing syntax, like this:

Run, Target , WorkingDir, Max|Min|Hide|UseErrorLevel, OutputVarPID

The square brackets denote optional parameters; the brackets themselves must be omitted from the actual code.

Sometimes the value or values a parameter accepts are written directly in the syntax block. For example, the third parameter of Run
shown above accepts one or more of the words shown, as text. The pipe symbol denotes alternatives; the symbol itself should be omitted from the actual code. The exact syntax of the parameter is described in the Parameters table, and varies between commands.

Optional Parameters

Optional parameters can simply be left blank. The comma preceding an optional parameter can also be omitted if all subsequent
parameters are omitted. For example, the Run command can accept between one and four parameters. All of the following are valid:

Run, notepad.exe, C:\

Run, notepad.exe,, Min

Run notepad.exe, , , notepadPID

Expressions vs Legacy Syntax

Many command parameters do not accept expressions by default. Use the percent-space prefix at the beginning of a parameter to


evaluate that parameter as an expression. In the following examples, the expression is shown on the first line (beginning after the percent sign), with pure legacy syntax shown on the second line.

MsgBox % 1+1  ; Shows "2"
MsgBox   1+1  ; Shows "1+1"

Literal text in an expression is always enclosed in quote marks. These are called quoted strings.

MsgBox % "This is text."
MsgBox    This is text.

Variables in an expression are never enclosed in percent signs, except to create a double reference.

MsgBox %  A_AhkVersion
MsgBox   %A_AhkVersion%

Variables cannot be used inside a quoted string.

MsgBox % "Hello %A_UserName%."  ; Shows "%A_UserName%"
MsgBox    Hello %A_UserName%.   ; Shows your username.

Instead, values are concatenated by writing them in sequence, separated by a space or tab, or a dot surrounded by spaces.

MsgBox % "Hello " . A_UserName . "."  ; Shows your username.

One alternative is to use the Format function, which can also format the parameter value in various ways.

MsgBox % Format("Hello {1}.", A_UserName)  ; {} also works in place of {1}.
A value is assigned to a variable with := instead of =:

MyVar := "This is text."
MyVar = This is text.

Comparisons are performed using the same symbols as legacy If: =, <> or !=, >, >=, < and <=.

if (Var1 = Var2)
if Var1 = %Var2%

In an expression, both values can be simple values or complex sub-expressions. A comparison can also be combined with other
conditions using operators such as and and or (which are equivalent to && and ||).

if (Var1 >= Low and Var1 <= High)
if Var1 between %Low% and %High%  

Different Equals

One common mistake is to write = where := is needed. For example:

Total = A + B   ; Assigns the literal text "A + B"

This can be difficult to avoid (at least until such time as the legacy assignment syntax is removed), but it may help to always use :=
where an assignment is intended.

The equal sign (when not used with another symbol, such as <=) has the following meanings:
Legacy assignment: Var = Value

Legacy If equal: if Var = Value

Case-insensitive equal: if (Expr1 = Expr2) (also valid in other expressions, not just if)
Assign after comma: x:=1, y=2, a=b=c (all are assignments due to a special rule)
Declare and initialize: local x = Expr (always accepts an expression)

Set parameter default value: MyFunc(Param="Default value") {...

The first two cases can be avoided by always using the := assignment operator and if (expression).
For the last three cases, := should have been used instead of =.

Commands vs Functions

In AutoHotkey v1, it is currently not possible to call a command from an expression, or to call a function using the command syntax.
However, several commands have a function replacement.

Command                                                             Replacement
FileAppend         FileOpen and File.Write


FileGetAttribFileExist

FileRead             FileOpen and File.Read

GetKeyStateGetKeyState (the function returns 0 or 1, not "U" or "D")
IfExist                 FileExist

IfInString            InStr

IfWinActiveWinActive

IfWinExistWinExist

StringGetPos      InStr

StringLen            StrLen

StringReplaceStrReplace

StringSplit           StrSplit

StringLower

StringUpper        Format("{:L}", input), Format("{:U}", input) or Format("{:T}", input) StringLeft

StringMid

StringRight

StringTrimLeft

StringTrimRight

 

Control Flow Statements

For a general explanation of control flow, see Control Flow.

Statements are grouped together into a block by enclosing them in braces {}, as in C, JavaScript and similar languages, but usually the
braces must appear at the start of a line. Control flow statements can be applied to an entire block or just a single statement.

The body of a control flow statement is always a single group of statements. A block counts as a single group of statements, as does a
control flow statement and its body. The following related statements are also grouped with each other, along with their bodies: If with Else; Loop/For with Until; Try with Catch and/or Finally. In other words, when a group of these statements is used as a whole, it does not always need to be enclosed in braces (however, some coding styles always include the braces, for clarity).

Control flow statements which have a body and therefore must always be followed by a related statement or group of statements: If,
Else, Loop, While, For, Try, Catch and Finally.

The following control flow statements exist:

A block (denoted by a pair of braces) groups zero or more statements to act as a single statement.

An If statement causes its body to be executed or not depending on a condition. It can be followed by an Else statement, which
executes only if the condition was not met.

Goto jumps to the specified label and continues execution.

Gosub calls a subroutine.

Return returns from a subroutine or function.

A Loop statement (Loop, While or For) executes its body repeatedly.

Break exits (terminates) a loop.

Continue skips the rest of the current loop iteration and begins a new one.

Until causes a loop to terminate when an expression evaluates to true. The expression is evaluated after each iteration.

Exception handling:

Try guards its body against runtime errors and exceptions thrown by the throw command.

Catch executes its body after an exception is thrown within a try statement (and only if an exception is thrown).
Finally executes its body when control is being transferred out of a try or catch statement's body.

Throw throws an exception to be handled by try/catch or display an error dialog.

Control Flow vs Commands

Control flow statements have syntax resembling commands, and are often referred to as such, but some differ from commands:
There are several types of If statement, with each having different syntax.

For and several types of If statement use keywords or an operator instead of commas to separate some of their parameters.

The opening brace of a block can be written at the end of the same line as an If (expression), Else, Loop Count, While, For, Try,
Catch or Finally statement (basically any control flow statement which does not use legacy syntax). This is referred to as the One
True Brace (OTB) style. It is not supported by the other Loop sub-commands or legacy If statement, as the brace would be
interpreted as a literal { character.

Else, Try and Finally allow any valid statement to their right, as they require a body but have no parameters.

If (expression) and While allow an open parenthesis to be used immediately after the name. For example, if(expression).

For, While, Until and Throw always accept expressions. They treat %var%, %var%000 and similar as expressions, whereas numeric
parameters of other commands do not. The requirement for backward-compatibility does not apply to these control flow statements


as they are relatively new.
If Statement

If (expression) evaluates an expression and executes the following statement only if the result is true.

Common cause of confusion: There are several other types of If statements, some of which look very similar to If (expression). These should be avoided in new scripts. If in doubt, it is best to always begin the expression with an open-parenthesis. The "legacy" If
statements are as follows:

If Var

If Var op Value, where op is one of the following operators: =, <>, !=, >, >=, <, <=.
If Var [not] between Lower and Upper

If Var [not] in/contains MatchList

If Var is [not] Type

Any If statement which does not match one of the usages shown above is interpreted as If (expression).
These are some common points of confusion related to legacy If statements:

Variable names must be enclosed in percent signs only on the right-hand side of the operator.
between, in, contains and is are only valid in this context; they cannot be used in expressions.
Multiple conditions cannot be written on the same line (such as with the and operator).

None of the parameters are expressions.

The following "legacy" named If statements also exist:

IfEqual, IfNotEqual, IfLess, IfLessOrEqual, IfGreater and IfGreaterOrEqual

If[Not]Exist
If[Not]InString
If[Not]WinActive
If[Not]WinExist
IfMsgBox

With the exception of IfMsgBox, these are all obsolete and generally should be avoided in new scripts.

Named If statements allow a command to be written on the same line, but mispelled command names are treated as literal text. Such
errors may be difficult to detect.

Loop Statement

There are several types of loop statements:

Loop Count executes a statement repeatedly: either the specified number of times or until break is encountered.

Loop Reg retrieves the contents of the specified registry subkey, one item at a time.

Loop Files retrieves the specified files or folders, one at a time.

Loop Parse retrieves substrings (fields) from a string, one at a time.

Loop Read retrieves the lines in a text file, one at a time.

While executes a statement repeatedly until the specified expression evaluates to false. The expression is evaluated before each
iteration.

For executes a statement once for each value or pair of values returned by an enumerator, such as each key-value pair in an object.

Break exits (terminates) a loop, effectively jumping to the next line after the loop's body.

Continue skips the rest of the current loop iteration and begins a new one.

Until causes a loop to terminate when an expression evaluates to true. The expression is evaluated after each iteration.

A label can be used to "name" a loop for Continue and Break. This allows the script to easily continue or break out of any number of
nested loops without using Goto.

The built-in variable A_Index contains the number of the current loop iteration. It contains 1 the first time the loop's body is executed. For the second time, it contains 2; and so on. If an inner loop is enclosed by an outer loop, the inner loop takes precedence. A_Index
works inside all types of loops, but contains 0 outside of a loop.

For some loop types, other built-in variables return information about the current loop item (registry key/value, file, substring or line of text). These variables have names beginning with A_Loop, such as A_LoopFileName and A_LoopReadLine. Their values always
correspond to the most recently started (but not yet stopped) loop of the appropriate type. For example, A_LoopField returns the current substring in the innermost parsing loop, even if it is used inside a file or registry loop.

t := "column 1`tcolumn 2`nvalue 1`tvalue 2"


Loop Parse, t, `n

{

    rowtext := A_LoopField

    rownum := A_Index  ; Save this for use in the second loop, below.
    Loop Parse, rowtext, `t

    {

        MsgBox %rownum%:%A_Index% = %A_LoopField%

    }

}

Loop variables can also be used outside the body of a loop, such as in a function or subroutine which is called from within a loop.
Not Control Flow

As directives, labels (including hotkeys and hotstrings), and declarations without assignments are processed when the script is loaded
from file, they are not subject to control flow. In other words, they take effect unconditionally, before the script ever executes any control flow statements. Similarly, the #If directives such as #IfWinActive cannot affect control flow; they merely set the criteria for any hotkey labels and hotstrings specified in the code. A hotkey's criteria is evaluated each time it is pressed, not when the #If directive is
encountered in the code.

Structure of a Script

Auto-execute Section

After the script has been loaded, it begins executing at the top line, continuing until a Return, Exit, the script's first hotkey/hotstring
label, or the physical end of the script is encountered (whichever comes first). This top portion of the script is referred to as the auto-
execute section, but it is really just a subroutine which is called after program startup.

Note: While the script's first hotkey/hotstring label has the same effect as return, other hotkeys and labels do not.

The auto-execute section is often used to configure settings which apply to every newly launched thread. For details, see The Top of the Script.

Subroutines

A subroutine (or sub) is a reusable block of code which can be called to perform some task.

Scripts use subroutines to define what should happen when a particular hotkey is pressed or some other event occurs. Scripts can also
call subroutines directly, by using Gosub.

Any label can be used as the starting point of a subroutine. A subroutine has no explicitly marked ending point, but instead ends if and
when control is returned to the subroutine's caller by Return or when the thread is exited. For example:

gosub Label1

Label1:

MsgBox %A_ThisLabel%
return

Note that as labels have no effect when reached during normal execution, in this example a MsgBox would be shown twice: once while the subroutine is running and again after it returns. One important consequence is that you cannot define one subroutine inside another
subroutine, because the "body" of the inner subroutine would execute automatically and then return, effectively terminating the outer
subroutine.

Subroutines should typically be defined separately to any other block of code, but can also be defined inside a function, allowing the
subroutine access to that function's static variables (and local variables, but only while the function is running).

Note: Subroutines defined inside a function have certain limitations regarding the use of local variables and dynamic variable references, including Gui control variables. For details, see Using Subroutines Within a Function.

User-Defined Functions

Generally speaking, a function is a kind of subroutine. However, within the AutoHotkey documentation, "subroutine" typically refers to the kind of subroutine defined by a label (described above).

User-defined functions differ from subroutines in that they can accept parameters and return a value, and they can have local variables. They can be called either by a function call within the script or by the program itself, such as if a function was passed to the Hotkey or
SetTimer commands.

Functions are defined using syntax resembling a function call followed by a block of code enclosed in braces:

MyFunction(FirstParameter, Second, ByRef Third, Fourth:="")

{


    ...

    return "a value"

}

As with function calls, there must be no space between the function name and open-parenthesis.

The line break between the close-parenthesis and open-brace is optional. There can be any amount of whitespace or comments between the two.

ByRef indicates that the parameter accepts a variable reference, making that parameter an alias for whichever variable the caller passes. If the caller does not pass a variable, the parameter acts as a normal local variable. ByRef parameters can also be optional.

Optional parameters are specified by following the parameter name with := or = and a default value, which must be a literal quoted
string, a number, true or false. The operators := and = are interchangeable for historical reasons, but it is best to use := for consistency with assignment in expressions.

The function can return a value. If it does not, the default return value is an empty string.

A function cannot be defined inside another function. Otherwise, the position of a function definition does not matter; any function
defined within the script can be called from anywhere else.

See Functions for much more detail.
#Include

The #Include directive causes the script to behave as though the specified file's contents are present at this exact position. This is often
used to organise code into separate files, or to make use of script libraries written by other users.

Note: The following paragraphs detail some common points of confusion.

When using #Include, it is important to consider what effect the file's contents would have if placed at that position, since #Include will have the same effect. For instance:

#Include generally should not be used in the middle of a subroutine or function.

The use of #Include in the script's auto-execute section requires special consideration, because the auto-execute section is
essentially just a subroutine. Execution of a subroutine halts if it reaches a return, regardless of which file that return is in.
Similarly, if the file contains a hotkey/hotstring, it may be considered the script's first hotkey/hotstring, which would act like
return.

The script only has one auto-execute section, not one per file.

#Include can be safely used within the auto-execute section to include files which contain only function definitions, since function

definitions (but not function calls) are skipped over during execution. If a file contains other code, one can avoid breaking the auto-
execute section by skipping over the file's contents with Goto.

Unlike in C/C++, #Include does nothing if the file has already been included by a previous directive. To include the contents of the same file multiple times, use #IncludeAgain.

Script files containing functions can be automatically included without having to use #Include, if they are saved in a standard location
and named appropriately. The effect is similar to using #Include at the end of the main script file. For details, see Libraries of Functions.

Miscellaneous

Dynamic Variables

A dynamic variable reference takes a text value and interprets it as the name of a variable.

The most common form of dynamic variable reference is called a double reference or double-deref. Before performing a double
reference, the name of the target variable is stored in a second variable. This second variable can then be used to assign a value to the
target variable indirectly, using a double reference. For example:

target := 42

second := "target"

MsgBox   %second%  ; Normal (single) variable reference in text => target

MsgBox %  second   ; Normal (single) variable reference in an expression => target
MsgBox % %second%  ; Double-deref in an expression => 42

At first, it would appear that percent signs have a different meaning depending on whether they are used in text or in an expression.
However, it may make more sense to think of %second% as being replaced with the contents of the variable second in both cases:

MsgBox %second%MsgBox target: Shows "target".


MsgBox % %second%MsgBox % target: Shows the contents of target, i.e. "42".

Currently, second must always contain a variable name in the second case; arbitrary expressions are not supported.

A dynamic variable reference can also take one or more pieces of literal text and the content of one or more variables, and join them
together to form a single variable name. This is done simply by writing the pieces of the name and percent-enclosed variables in
sequence, without any spaces. For example, MyArray%A_Index% or MyGrid%X%_%Y%. This is used to access pseudo-arrays, described
below.

For a description of how dynamic variable references inside functions are resolved, see Functions: More about locals and globals.

Pseudo-arrays

A pseudo-array is actually just a bunch of discrete variables, but with a naming pattern which allows them to be used like elements of an array. For example:

MyArray1 = A
MyArray2 = B
MyArray3 = C
Loop 3

    MsgBox % MyArray%A_Index%  ; Shows A, then B, then C.

As the individual elements are just normal variables, one can assign or retrieve a value, but cannot remove or insert elements. Because
the pseudo-array itself doesn't really exist, it can't be passed to or returned from a function, or copied as a whole. For these reasons, it is generally recommended to use normal arrays instead, where possible.

Associative pseudo-arrays

The "index" used to form the final variable name does not have to be numeric; it could instead be a letter or keyword, making the
pseudo-array similar to an associative array or an object. The following example creates a pseudo-array with elements "Left", "Top",
"Right" and "Bottom":

SysGet, WA, MonitorWorkArea

MsgBox, Left: %WALeft% -- Top: %WATop% -- Right: %WARight% -- Bottom: %WABottom%.

Commands which create pseudo-arrays

There are several commands which create associative pseudo-arrays:
GuiControlGet Pos.

RegExMatch, except when given the O) option, which causes it to output a single object containing all match information.
SysGet Monitor/MonitorWorkArea, as demonstrated above.

StringSplit. New scripts should use StrSplit() instead, as it creates a normal array.

WinGet List.

Caution: These commands do not follow the same rules as dynamic variable references. If used within a function, the resulting pseudo- array is either entirely global or entirely local, depending only on the first element (or base name) of the array. Some of the variables in the pseudo-array may be inaccessible if they are not individually declared. For details, see Functions: More about locals and globals.

AutoHotkey also creates one global pseudo-array to contain any command line parameters that were passed to the script.
Labels

A label identifies a line of code, and can be used as a Goto target or to form a subroutine. There are three kinds of label: normal named
labels, hotkey labels and hotstring labels.

Normal labels consist of a name followed by a colon.

this_is_a_label:

Hotkey labels consist of a hotkey followed by double-colon.

^a::

Hotstring labels consist of a colon, zero or more options, another colon, an abbreviation and double-colon.

:*:btw::

Generally, aside from whitespace and comments, no other code can be written on the same line as a label. However:

A hotkey label can be directly followed by a command or other statement to create a one-line hotkey. In other words, if a
command, assignment or expression is present on the same line as a hotkey label, it acts as though followed by return.


A hotkey with a key name written to the right of the double-colon is actually a remapping, which is shorthand for a pair of
hotkeys. For example, a::b creates hotkeys and labels for *a and *a Up, and does not create a label named a.

A hotstring with text written to the right of the final double-colon is an auto-replace hotstring. Auto-replace hotstrings do not act
as labels.

For more details, see Labels.


Software License

GNU GENERAL PUBLIC LICENSE

Version 2, June 1991

Copyright (C) 1989, 1991 Free Software Foundation, Inc.

51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA

Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.

Preamble

The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too.

When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things.

To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it.

For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you
have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their
rights.

We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software.

Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the
original, so that any problems introduced by others will not reflect on the original authors' reputations.

Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent
must be licensed for everyone's free use or not licensed at all.

The precise terms and conditions for copying, distribution and modification follow.

TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
MODIFICATION

0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the
Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a
portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without
limitation in the term "modification".) Each licensee is addressed as "you".

Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.

1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.

You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.

2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:

a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.


b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.

c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does
not normally print such an announcement, your work based on the Program is not required to print an announcement.)

These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and
can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.

Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or collective works based on the Program.

In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a
volume of a storage or distribution medium does not bring the other work under the scope of this License.

3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:

a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of
Sections 1 and 2 above on a medium customarily used for software interchange; or,

b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of
physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed
under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,

c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an
offer, in accord with Subsection b above.)

The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete
source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component itself accompanies the executable.

If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy
the source along with the object code.

4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.

5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.

6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to
this License.

7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do
not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you,
then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.

If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.

It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such
claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by
public license practices. Many people have made generous contributions to the wide range of software distributed through that system in


reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software
through any other system and a licensee cannot impose that choice.

This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.

8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those
countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the
limitation as if written in the body of this License.

9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.

Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by
the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever

published by the Free Software Foundation.

10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the
author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of
our free software and of promoting the sharing and reuse of software generally.

NO WARRANTY

11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT
HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

END OF TERMS AND CONDITIONS


Objects

An object in AutoHotkey is an abstract datatype which provides three basic functions:
GET a value.

SET a value.

CALL a method (that is, a function which does something with the target object).

Related topics:

Objects: General explanation of objects.

Object Protocol: Specifics about how a script interacts with an object.
IsObject can be used to determine if a value is an object:

Result := IsObject(expression)
Types of objects include:

Object - scriptable associative array.

File - provides an interface for file input/output.

Function objects - Func, BoundFunc or user-defined.

ComObject - wraps an IDispatch interface (a COM or "Automation" object).

Support for objects requires [AHK_L 31+], but some features may require later a version.
Table of Contents

Basic Usage - Simple Arrays, Associative Arrays, Objects, Freeing Objects, Remarks
Extended Usage - Function References, Arrays of Arrays, Arrays of Functions
Custom Objects - Prototypes, Classes, Construction and Destruction, Meta-Functions
Default Base Object - Automatic Var Init, Pseudo-Properties, Debugging
Implementation - Reference-Counting, Pointers to Objects

Basic Usage

Simple Arrays [v1.1.21+]

Create an array:

Array := [Item1, Item2, ..., ItemN]
Array := Array(Item1, Item2, ..., ItemN)

Retrieve an item:

Value := Array[Index]
Assign an item:

Array[Index] := Value

Insert one or more items at a given index:

Array.InsertAt(Index, Value, Value2, ...)
Append one or more items:

Array.Push(Value, Value2, ...)
Remove an item:

RemovedValue := Array.RemoveAt(Index)
Remove the last item:

RemovedValue := Array.Pop()

If the array is not empty, MinIndex and MaxIndex/Length return the lowest and highest index currently in use in the array. Since the
lowest index is nearly always 1, MaxIndex usually returns the number of items. However, if there are no integer keys, MaxIndex returns an empty string whereas Length returns 0. Looping through an array's contents can be done either by index or with a For-loop. For
example:


array := ["one", "two", "three"]

; Iterate from 1 to the end of the array:
Loop % array.Length()

    MsgBox % array[A_Index]

; Enumerate the array's contents:

For index, value in array

    MsgBox % "Item " index " is '" value "'"

Associative Arrays [v1.1.21+]

An associative array is an object which contains a collection of unique keys and a collection of values, where each key is associated with one value. Keys can be strings, integers or objects, while values can be of any type. An associative array can be created as follows:

Array := {KeyA: ValueA, KeyB: ValueB, ..., KeyZ: ValueZ}

Array := Object("KeyA", ValueA, "KeyB", ValueB, ..., "KeyZ", ValueZ)

Using the {key:value} notation, quote marks are optional for keys which consist only of word characters. Any expression can be used as a key, but to use a variable as a key, it must be enclosed in parentheses. For example, {(KeyVar): Value} and {GetKey(): Value} are both valid.

Retrieve an item:

Value := Array[Key]
Assign an item:

Array[Key] := Value
Remove an item:

RemovedValue := Array.Delete(Key)
Enumerating items:

array := {ten: 10, twenty: 20, thirty: 30}
For key, value in array

    MsgBox %key% = %value%

Associative arrays can be sparsely populated - that is, {1:"a",1000:"b"} contains only two key-value pairs, not 1000.

In AutoHotkey v1.x, simple arrays and associative arrays are the same thing. However, treating [] as a simple linear array helps to keep its role clear, and improves the chance of your script working with a future version of AutoHotkey, which might differentiate between
simple arrays and associative arrays.

Objects [AHK_L 31+]

For all types of objects, the notation Object.LiteralKey can be used to access a property, array element or method, where LiteralKey is an identifier or integer and Object is any expression. Identifiers are unquoted strings which may consist of alphanumeric characters,
underscore and, in [v1.1.09+], non-ASCII characters. For example, match.Pos is equivalent to match["Pos"] while arr.1 is equivalent to arr[1]. There must be no space after the dot.

Examples:

Retrieve a property:

Value := Object.Property
Set a property:

Object.Property := Value
Call a method:

ReturnValue := Object.Method(Parameters)
Call a method with a computed method name:

ReturnValue := Object[MethodName](Parameters)

Some properties of COM objects and user-defined objects can accept parameters:

Value := Object.Property[Parameters]
Object.Property[Parameters] := Value

Related: Object, File Object, Func Object, COM object


Known limitation:

Currently x.y[z]() is treated as x["y", z](), which is not supported. As a workaround, (x.y)[z]() evaluates x.y first, then

uses the result as the target of the method call. Note that x.y[z].Call() does not have this limitation since it is evaluated the same
as (x.y[z]).Call().

Freeing Objects

Scripts do not free objects explicitly. When the last reference to an object is released, the object is freed automatically. A reference stored in a variable is released automatically when that variable is assigned some other value. For example:

obj := {}  ; Creates an object.

obj := ""  ; Releases the last reference, and therefore frees the object.

Similarly, a reference stored in a field of another object is released when that field is assigned some other value or removed from the
object. This also applies to arrays, which are actually objects.

arr := [{}]  ; Creates an array containing an object.

arr[1] := {}  ; Creates a second object, implicitly freeing the first object.
arr.RemoveAt(1)  ; Removes and frees the second object.

Because all references to an object must be released before the object can be freed, objects containing circular references aren't freed
automatically. For instance, if x.child refers to y and y.parent refers to x, clearing x and y is not sufficient since the parent object still contains a reference to the child and vice versa. To resolve this situation, remove the circular reference.

x := {}, y := {}             ; Create two objects.

x.child := y, y.parent := x  ; Create a circular reference.

y.parent := ""               ; The circular reference must be removed before the objects can be freed.
x := "", y := ""             ; Without the above line, this would not free the objects.

For more advanced usage and details, see Reference Counting.
Remarks

Syntax

All types of objects support both array syntax (brackets) and object syntax (dots).
Additionally, object references can themselves be used in expressions:

When an object reference is compared with some other value using =, ==, != or <>, they are considered equal only if both values
are references to the same object.

Objects are always considered true when a boolean value is required, such as in if obj, !obj or obj ? x : y.

An object's address can be retrieved using the &address-of operator. This uniquely identifies the object from the point of its
creation to the moment its last reference is released.

If an object is used in any context where an object is not expected, it is treated as an empty string. For example, MsgBox %object% shows an empty MsgBox and object + 1 yields an empty string. Do not rely on this behaviour as it may change.

When a method-call is followed immediately by an assignment operator, it is equivalent to setting a property with parameters. For
example, the following are equivalent:

obj.item(x) := y
obj.item[x] := y

Compound assignments such as x.y += 1 and --arr[1] are supported.

[v1.1.20+]: Parameters can be omitted when getting or setting properties. For example, x[,2]. Scripts can utilize this by defining default values for parameters in properties and meta-functions. The method name can also be completely omitted, as in x[](a). Scripts can
utilize this by defining a default value for the __Call meta-function's first parameter, since it is not otherise supplied with a value. Note
that this differs from x.(a), which is equivalent to x[""](a). If the property or method name is omitted when invoking a COM object,
its "default member" is invoked.

Keys

Some limitations apply to which values can be used as keys in objects created with [], {} or the new operator:

Integer keys are stored using the native signed integer type. AutoHotkey 32-bit supports integer keys in the range -2147483648 to

2147483647. AutoHotkey supports 64-bit integers, but only AutoHotkey 64-bit supports the full range as keys in an object.

As a consequence of the point above, the string format of integer values is not retained. For example, x[0x10], x[16] and
x[00016] are equivalent. This also applies to numeric strings which don't have a decimal point.

Quoted literal strings are considered purely non-numeric in v1.x, so x[1] and x["1"] are not equivalent. Additionally, if a quoted


literal string is concatenated with another value (as in "0x" x), the result is treated as purely non-numeric. However, this does not
apply to variables, so x[1] and x[y:="1"] are equivalent. This issue will be resolved in AutoHotkey v2, so scripts should avoid
using quoted numeric literals as keys.

Floating-point numbers are not supported as keys - instead they are converted to strings. In v1.x, floating-point literals retain their
original format whereas pure floating-point numbers (such as the result of 0+1.0 or Sqrt(y)) are forced into the current float
format. For consistency and clarity, scripts should avoid using floating-point literals as keys.

By default, the string key "base" corresponds to the object's base property, so cannot be used for storing ordinary values with a
normal assignment. However, any property can be overridden by storing a value by some other means, such as
ObjRawSet(Object, "base", "") or Object.SetCapacity("base", 0). Once this is done, the key "base" acts like any other
string.

Although built-in method names such as "Length" can be used as keys, storing a value will prevent the corresponding method from
being called (unless that value is a reference to the appropriate function, such as ObjLength).

Extended Usage

Function References [v1.1.00+]

If the variable func contains a function name, the function can be called one of two ways: %func%() or func.(). However, this requires the function name to be resolved each time, which is inefficient if the function is called more than once. To improve performance, the
script can retrieve a reference to the function and store it for later use:

Func := Func("MyFunc")

A function can be called by reference using the following syntax:

RetVal := %Func%(Params)     ; Requires [v1.1.07+]
RetVal := Func.Call(Params)  ; Requires [v1.1.19+]
RetVal := Func.(Params)      ; Not recommended

For details about additional properties of function references, see Func Object.
Arrays of Arrays

AutoHotkey supports "multi-dimensional" arrays by transparently storing arrays inside other arrays. For example, a table could be
represented as an array of rows, where each row is itself an array of columns. In that case, the content of column y of row x can be set
using either of the methods below:

table[x][y] := content  ; A
table[x, y] := content  ; B

If table[x] does not exist, A and B differ in two ways:

A fails whereas B automatically creates an object and stores it in table[x].

If table's base defines meta-functions, they are invoked as follows:

table.base.__Get(table, x)[y] := content   ; A
table.base.__Set(table, x, y, content)     ; B

Consequently, B allows the object to define custom behaviour for the overall assignment.
Multi-dimensional assignments such as table[a, b, c, d] := value are handled as follows:

If there is only one key remaining, perform the assignment and return. Otherwise:

Search the object for the first key in the list.

If a non-object is found, fail.

If an object is not found, create one and store it.

Recursively invoke the sub-object, passing the remaining keys and value - repeat from the top.

This behaviour only applies to script-created objects, not more specialized types of objects such as COM objects or COM arrays.
Arrays of Functions

An array of functions is simply an array containing function names or references. For example:

array := [Func("FirstFunc"), Func("SecondFunc")]

; Call each function, passing "foo" as a parameter:
Loop 2

    array[A_Index].Call("foo")

; Call each function, implicitly passing the array itself as a parameter:
Loop 2

    array[A_Index]()


FirstFunc(param) {

    MsgBox % A_ThisFunc ": " (IsObject(param) ? "object" : param)

}

SecondFunc(param) {

    MsgBox % A_ThisFunc ": " (IsObject(param) ? "object" : param)

}

For backward-compatibility, the second form will not pass array as a parameter if array[A_Index] contains a function name instead of a function reference. However, if array[A_Index] is inherited from array.base[A_Index], array will be passed as a parameter.

Custom Objects

Objects created by the script do not need to have any predefined structure. Instead, each object can inherit properties and methods from

its base object (otherwise known as a "prototype" or "class"). Properties and methods can also be added to (or removed from) an object at any time, and those changes will affect any and all derived objects. For more complex or specialized situations, a base object can override the standard behaviour of any objects derived from it by defining meta-functions.

Base objects are just ordinary objects, and are typically created one of two ways:

class baseObject {
    static foo := "bar"

}

; OR

baseObject := {foo: "bar"}

To create an object derived from another object, scripts can assign to the base property or use the new keyword:

obj1 := Object(), obj1.base := baseObject
obj2 := {base: baseObject}

obj3 := new baseObject

MsgBox % obj1.foo " " obj2.foo " " obj3.foo

It is possible to reassign an object's base at any time, effectively replacing all of the properties and methods that the object inherits.
Prototypes

Prototype or base objects are constructed and manipulated the same as any other object. For example, an ordinary object with one
property and one method might be constructed like this:

; Create an object.

thing := {}

; Store a value.

thing.foo := "bar"

; Create a method by storing a function reference.
thing.test := Func("thing_test")

; Call the method.

thing.test()

thing_test(this) {
    MsgBox % this.foo

}

When thing.test() is called, thing is automatically inserted at the beginning of the parameter list. However, for backward-
compatibility, this does not occur when a function is stored by name (rather than by reference) directly in the object (rather than being
inherited from a base object). By convention, the function is named by combining the "type" of object and the method name.

An object is a prototype or base if another object derives from it:

other := {}
other.base := thing
other.test()

In this case, other inherits foo and test from thing. This inheritance is dynamic, so if thing.foo is modified, the change will be reflected by other.foo. If the script assigns to other.foo, the value is stored in other and any further changes to thing.foo will have no effect
on other.foo. When other.test() is called, its this parameter contains a reference to other instead of thing.

Classes [v1.1.00+]

At its root, a "class" is a set or category of things having some property or attribute in common. Since a base or prototype object defines
properties and behaviour for set of objects, it can also be called a class object. For convenience, base objects can be defined using the
"class" keyword as shown below:

class ClassName extends BaseClassName

{

    InstanceVar := Expression
    static ClassVar := Expression


    class NestedClass
    {

        ...

    }

    Method()
    {
        ...
    }

    Property[]  ; Brackets are optional
    {

        get {

            return ...

        }

        set {

            return ... := value

        }

    }

}

When the script is loaded, this constructs an object and stores it in the global (or [in v1.1.05+] super-global) variable ClassName. To
reference this class inside a force-local function (or an assume-local or assume-static function prior to [v1.1.05]), a declaration such as
global ClassName is required. If extends BaseClassName is present, BaseClassName must be the full name of another class (but as of [v1.1.11], the order that they are defined in does not matter). The full name of each class is stored in object.__Class.

Because the class is referenced via a variable, the class name cannot be used to both reference the class and create a separate variable
(such as to hold an instance of the class) in the same context. For example, box := new Box would replace the class object in Box with an instance of itself. [v1.1.27+]: #Warn ClassOverwrite enables a warning to be shown at load time for each attempt to overwrite a class.

Within this documentation, the word "class" on its own usually means a class object constructed with the class keyword.
Class definitions can contain variable declarations, method definitions and nested class definitions.

Instance Variables [v1.1.01+]

An instance variable is one that each instance of the class (that is, each object derived from the class) has its own copy of. They are
declared like normal assignments, but the this. prefix is omitted (only directly within the class body):

InstanceVar := Expression

These declarations are evaluated each time a new instance of the class is created with the new keyword. The method name __Init is
reserved for this purpose, and should not be used by the script. The __New() method is called after all such declarations have been
evaluated, including those defined in base classes. Expression can access other instance variables and methods via this, but all other
variable references are assumed to be global.

To access an instance variable (even within a method), always specify the target object; for example, this.InstanceVar.

[v1.1.08+]: Declarations like x.y := z are also supported, provided that x was previously declared in this class. For example, x := {}, x.y := 42 declares x and also initializes this.x.y.

Static/Class Variables [v1.1.00.01+]

Static/class variables belong to the class itself, but can be inherited by derived objects (including sub-classes). They are declared like
instance variables, but using the static keyword:

static ClassVar := Expression

Static declarations are evaluated only once, before the auto-execute section, in the order they appear in the script. Each declaration stores a value in the class object. Any variable references in Expression are assumed to be global.

To assign to a class variable, always specify the class object; for example, ClassName.ClassVar := Value. If an object x is derived
from ClassName and x itself does not contain the key "ClassVar", x.ClassVar may also be used to dynamically retrieve the value of
ClassName.ClassVar. However, x.ClassVar := y would store the value in x, not in ClassName.

[v1.1.08+]: Declarations like static x.y := z are also supported, provided that x was previously declared in this class. For example,
static x := {}, x.y := 42 declares x and also initializes ClassName.x.y.

Nested Classes

Nested class definitions allow a class object to be stored inside another class object rather than a separate global variable. In the example above, class NestedClass constructs an object and stores it in ClassName.NestedClass. Sub-classes could inherit NestedClass or
override it with their own nested class (in which case new this.NestedClass could be used to instantiate whichever class is
appropriate).


class NestedClass

{

    ...

}

Methods

Method definitions look identical to function definitions. Each method has a hidden parameter named this, which typically contains a
reference to an object derived from the class. However, it could contain a reference to the class itself or a derived class, depending on
how the method was called. Methods are stored by reference in the class object.

Method()

{

    ...

}

Inside a method, the pseudo-keyword base can be used to access the super-class versions of methods or properties which are overridden in a derived class. For example, base.Method() in the class defined above would call the version of Method which is defined by
BaseClassName. Meta-functions are not called; otherwise, base.Method() behaves like BaseClassName.Method.Call(this). That is,

base.Method() always invokes the base of the class where the current method was defined, even if this is derived from a sub-
class of that class or some other class entirely.

base.Method() implicitly passes this as the first (hidden) parameter.

base only has special meaning if followed by a dot . or brackets [], so code like obj := base, obj.Method() will not work. Scripts
can disable the special behaviour of base by assigning it a non-empty value; however, this is not recommended. Since the variable base must be empty, performance may be reduced if the script omits #NoEnv.

Properties [v1.1.16+]

Property definitions allow a method to be executed whenever the script gets or sets a specific key.

Property[]

{

    get {

        return ...

    }

    set {

        return ... := value
    }

}

Property is simply the name of the property, which will be used to invoke it. For example, obj.Property would call get while
obj.Property := value would call set. Within get or set, this refers to the object being invoked. Within set, value contains the value being assigned.

Parameters can be passed by enclosing them in square brackets to the right of the property name, both when defining the property and
when calling it. Aside from using square brackets, parameters of properties are defined the same way as parameters of methods -
optional, ByRef and variadic parameters are supported.

The return value of get or set becomes the result of the sub-expression which invoked the property. For example, val := obj.Property := 42 stores the return value of set in val.

Each class can define one or both halves of a property. If a class overrides a property, it can use base.Property to access the property
defined by its base class. If get or set is not defined, it can be handled by a base class. If set is not defined and is not handled by a meta- function or base class, assigning a value stores it in the object, effectively disabling the property.

Internally, get and set are two separate methods, so cannot share variables (except by storing them in this).

Meta-functions provide a broader way of controlling access to properties and methods of an object, but are more complicated and error- prone.

Construction and Destruction

Whenever a derived object is created with the new keyword [requires v1.1.00+], the __New method defined by its base object is called.
This method can accept parameters, initialize the object and override the result of the new operator by returning a value. When an object is destroyed, __Delete is called. For example:

m1 := new GMem(0, 20)

m2 := {base: GMem}.__New(0, 30)

class GMem

{

    __New(aFlags, aSize)
    {


        this.ptr := DllCall("GlobalAlloc", "UInt", aFlags, "Ptr", aSize, "Ptr")
        if !this.ptr

            return ""

        MsgBox % "New GMem of " aSize " bytes at address " this.ptr "."
        return this  ; This line can be omitted when using the 'new' operator.
    }

    __Delete()

    {

        MsgBox % "Delete GMem at address " this.ptr "."
        DllCall("GlobalFree", "Ptr", this.ptr)

    }

}

__Delete is not called for any object which has the key "__Class". Class objects have this key by default.

[v1.1.28+]: If an exception or runtime error is thrown while __Delete is executing and is not handled within __Delete, it acts as though
__Delete was called from a new thread. That is, an error dialog is displayed and __Delete returns, but the thread does not exit (unless it
was already exiting). Prior to v1.1.28, unhandled exceptions caused inconsistent behavior.

Meta-Functions

Method syntax:

class ClassName {

    __Get([Key, Key2, ...])
    __Set([Key, Key2, ...], Value)
    __Call(Name [, Params...])

}

Function syntax:

MyGet(this [, Key, Key2, ...])
MySet(this [, Key, Key2, ...], Value)
MyCall(this, Name [, Params...])

ClassName := { __Get: Func("MyGet"), __Set: Func("MySet"), __Call: Func("MyCall") }

Meta-functions define what happens when a key is requested but not found within the target object. For example, if obj.key has not been assigned a value, it invokes the __Get meta-function. Similarly, obj.key := value invokes __Set and obj.key() invokes __Call. These meta-functions (or methods) would need to be defined in obj.base, obj.base.base or such.

When the script gets, sets or calls a key which does not exist within the target object, the base object is invoked as follows:

If this base object defines the appropriate meta-function, call it. If the meta-function explicitly returns, use the return value as the

result of the operation (whatever caused the meta-function to be called) and return control to the script. Otherwise, continue as
described below.

Set: If the meta-function handled an assignment, it should return the value which was assigned. This allows assignments to be
chained, as in a.x := b.y := z. The return value may differ from the original value of z (for instance, if restrictions are imposed
on which values can be assigned).

Search for a matching key in the base object's own fields.

[v1.1.16+]: If a key corresponding to a property is found and it implements get or set (as appropriate), invoke the property and
return. If this is a method call, invoke get.

If no key was found, recursively invoke this base object's own base (apply each of these steps to it, starting at the top of this list). If
we're not finished yet, search this base object for a matching key again in case one was added by a meta-function.

Due to backward-compatibility, this step is performed for set operations even if a key was found (unless it defines a property

which implements set).

If multiple parameters were given for get or set and a key was found, check its value. If that value is an object, handle the
remaining parameters by invoking it, and do nothing further.

If a key was found,

Get: Return the value.

Call: Attempt to call the value, passing the target object as the first parameter (this). The value should be a function name or a
function object.

If a meta-function stores a matching key in the object but does not return, the behaviour is the same as if the key initially existed in the object. For an example using __Set, see Sub-classing Arrays of Arrays.

If the operation still hasn't been handled, check if this is a built-in method or property:
Get: If the key is "base", return the object's base.

Set: If the key is "base", set the object's base (or remove it if the value isn't an object).
Call: Call a built-in method if applicable.


If the operation still hasn't been handled,
Get and Call: Return an empty string.

Set: If only one key parameter was given, store the key and value in the target object and return the assigned value. If multiple
parameters were given, create a new object and store it using the first parameter as a key, then handle the remaining parameters by
invoking the new object. (See Arrays of Arrays.)

Known limitation:

Using return without a value is equivalent to return "". This may be changed in a future version so that return can be used to

"escape" from a meta-function without overriding the default behaviour.

Dynamic Properties

Property syntax can be used to define properties which compute a value each time they are evaluated, but each property must be known in advance and defined individually in the script. By contrast, __Get and __Set can be used to implement properties which aren't known by the script.

For example, a "proxy" object could be created which sends requests for properties over the network (or through some other channel). A remote server would send back a response containing the value of the property, and the proxy would return the value to its caller. Even if the name of each property was known in advance, it would not be logical to define each property individually in the proxy class since

every property does the same thing (send a network request). Meta-functions receive the property name as a parameter, so are a good
solution for this problem.

Another use of __Get and __Set is to implement a set of related properties which share code. In the example below they are used to
implement a "Color" object with R, G, B and RGB properties, where only the RGB value is actually stored:

red  := new Color(0xff0000), red.R -= 5

cyan := new Color(0), cyan.G := 255, cyan.B := 255

MsgBox % "red: " red.R "," red.G "," red.B " = " red.RGB
MsgBox % "cyan: " cyan.R "," cyan.G "," cyan.B " = " cyan.RGB

class Color

{

    __New(aRGB)

    {

        this.RGB := aRGB
    }

    static Shift := {R:16, G:8, B:0}

    __Get(aName)

    {

        ; NOTE: Using this.Shift here would cause an infinite loop!
        shift := Color.Shift[aName]  ; Get the number of bits to shift.
        if (shift != "")  ; Is it a known property?

            return (this.RGB >> shift) & 0xff

        ; NOTE: Using 'return' here would break this.RGB.

    }

    __Set(aName, aValue)

    {

        if ((shift := Color.Shift[aName]) != "")

        {

            aValue &= 255  ; Truncate it to the proper range.

            ; Calculate and store the new RGB value.

            this.RGB := (aValue << shift) | (this.RGB & ~(0xff << shift))

            ; 'Return' must be used to indicate a new key-value pair should not be created.
            ; This also defines what will be stored in the 'x' in 'x := clr[name] := val':
            return aValue

        }

        ; NOTE: Using 'return' here would break this.stored_RGB and this.RGB.

    }

    ; Meta-functions can be mixed with properties:
    RGB {

        get {

            ; Return it in hex format:
            return format("0x{:06x}", this.stored_RGB)
        }

        set {

            return this.stored_RGB := value

        }

    }

}

However, in this case Property syntax could have been used instead, where code is shared by simply having each property call a central


method. It is better to avoid using meta-functions where possible due to the high risk of misuse (see the notes in red above).

Objects as Functions

For an outline of how to create objects which can act as functions, see Function Objects.

A function object can also act as a meta-function, such as to define dynamic properties similar to those in the previous section. Although it is recommended to use property syntax instead, the example below shows the potential of meta-functions for implementing new
concepts or behaviour, or changing the structure of the script.

blue := new Color(0x0000ff)

MsgBox % blue.R "," blue.G "," blue.B

class Properties extends FunctionObject

{

    Call(aTarget, aName, aParams*)

    {

        ; If this Properties object contains a definition for this half-property, call it.
        if ObjHasKey(this, aName)

            return this[aName].Call(aTarget, aParams*)

    }

}

class Color

{

    __New(aRGB)

    {

        this.RGB := aRGB
    }

    class __Get extends Properties

    {

        R() {

            return (this.RGB >> 16) & 255
        }

        G() {

            return (this.RGB >> 8) & 255
        }

        B() {

            return this.RGB & 255

        }

    }

    ;...

}

Sub-classing Arrays of Arrays

When a multi-parameter assignment such as table[x, y] := content implicitly causes a new object to be created, the new object
ordinarily has no base and therefore no custom methods or special behaviour. __Set may be used to initialize these objects, as
demonstrated below.

x := {base: {addr: Func("x_Addr"), __Set: Func("x_Setter")}}

; Assign value, implicitly calling x_Setter to create sub-objects.
x[1,2,3] := "..."

; Retrieve value and call example method.

MsgBox % x[1,2,3] "`n" x.addr() "`n" x[1].addr() "`n" x[1,2].addr()

x_Setter(x, p1, p2, p3) {
    x[p1] := new x.base

}

x_Addr(x) {
    return &x

}

Since x_Setter has four mandatory parameters, it will only be called when there are two or more key parameters. When the assignment above occurs, the following takes place:

x[1] does not exist, so x_Setter(x,1,2,3) is called ("..." is not passed as there are too few parameters).
x[1] is assigned a new object with the same base as x.

No value is returned – the assignment continues.

x[1][2] does not exist, so x_Setter(x[1],2,3,"...") is called.

x[1][2] is assigned a new object with the same base as x[1].
No value is returned – the assignment continues.

x[1][2][3] does not exist, but since x_Setter requires four parameters and there are only three (x[1][2], 3, "..."), it is not
called and the assignment completes as normal.


Default Base Object

When a non-object value is used with object syntax, the default base object is invoked. This can be used for debugging or to globally
define object-like behaviour for strings, numbers and/or variables. The default base may be accessed by using .base with any non-object value; for instance, "".base. Although the default base cannot be set as in "".base := Object(), the default base may itself have a base as in "".base.base := Object().

Automatic Var Init

When an empty variable is used as the target of a set operation, it is passed directly to the __Set meta-function, giving it opportunity to
insert a new object into the variable. For brevity, this example does not support multiple parameters; it could, by using a variadic
function.

"".base.__Set := Func("Default_Set_AutomaticVarInit")
empty_var.foo := "bar"

MsgBox % empty_var.foo

Default_Set_AutomaticVarInit(ByRef var, key, value)

{

    if (var = "")

        var := Object(key, value)

}

Pseudo-Properties

Object "syntax sugar" can be applied to strings and numbers.

"".base.__Get := Func("Default_Get_PseudoProperty")
"".base.is    := Func("Default_is")

MsgBox % A_AhkPath.length " == " StrLen(A_AhkPath)
MsgBox % A_AhkPath.length.is("integer")

Default_Get_PseudoProperty(nonobj, key)

{

    if (key = "length")
        return StrLen(nonobj)

}

Default_is(nonobj, type)

{

    if nonobj is %type%
        return true
    return false

}

Note that built-in functions may also be used, but in this case the parentheses cannot be omitted:

"".base.length := Func("StrLen")

MsgBox % A_AhkPath.length() " == " StrLen(A_AhkPath)

Debugging

If allowing a value to be treated as an object is undesirable, a warning may be shown whenever a non-object value is invoked:

"".base.__Get := "".base.__Set := "".base.__Call := Func("Default__Warn")
empty_var.foo := "bar"

x := (1 + 1).is("integer")

Default__Warn(nonobj, p1="", p2="", p3="", p4="")

{

    ListLines

    MsgBox A non-object value was improperly invoked.`n`nSpecifically: %nonobj%

}

Implementation

Reference-Counting

AutoHotkey uses a basic reference-counting mechanism to automatically free the resources used by an object when it is no longer
referenced by the script. Script authors should not invoke this mechanism explicitly, except when dealing directly with unmanaged
pointers to objects.

Currently in AutoHotkey v1.1, temporary references created within an expression (but not stored anywhere) are released immediately
after use. For example, Fn(&{}) passes an invalid address to the function, because the temporary reference returned by {} is released


immediately after the address-of operator is evaluated.

To run code when the last reference to an object is being released, implement the __Delete meta-function.
Known Limitations:

Circular references must be broken before an object can be freed. For details and an example, see Freeing Objects.

Although references in static and global variables are released automatically when the program exits, references in non-static local
variables or on the expression evaluation stack are not. These references are only released if the function or expression is allowed
to complete normally.

Although memory used by the object is reclaimed by the operating system when the program exits, __Delete will not be called unless all references to the object are freed. This can be important if it frees other resources which are not automatically reclaimed by the operating system, such as temporary files.

Pointers to Objects

In some rare cases it may be necessary to pass an object to external code via DllCall or store it in a binary data structure for later

retrieval. An object's address can be retrieved via address := &object; however, this effectively makes two references to the object, but the program only knows about the one in object. If the last known reference to the object was released, the object would be deleted.
Therefore, the script must inform the object that it has gained a reference. There are two ways to do this:

; Method #1: Explicitly increment the reference count.
address := &object

ObjAddRef(address)

; Method #2: Use Object(), which increments the reference count and returns an address.
address := Object(object)

This function can also be used to convert an address back into a reference:

object := Object(address)

Either way, the script must also inform the object when it is finished with that reference:

; Decrement the object's reference count to allow it to be freed:
ObjRelease(address)

Generally each new copy of an object's address should be treated as another reference to the object, so the script should call ObjAddRef when it gains a copy and ObjRelease immediately before losing one. For example, whenever an address is copied via something like x
:= address, ObjAddRef should be called. Similarly, when the script is finished with x (or is about to overwrite x's value), it should call ObjRelease.

Note that the Object() function can be used even on objects which it did not create, such as COM objects and File objects.


Using the Program

AutoHotkey doesn't do anything on its own; it needs a script to tell it what to do. A script is simply a plain text file with the .ahk
filename extension containing instructions for the program, like a configuration file, but much more powerful. A script can do as little as performing a single action and then exiting, but most scripts define a number of hotkeys, with each hotkey followed by one or more
actions to take when the hotkey is pressed.

#z::Run https://autohotkey.com  ; Win+Z
^!n::  ; Ctrl+Alt+N

if WinExist("Untitled - Notepad")
    WinActivate

else

    Run Notepad

return

Tip: If your browser supports it, you can download any code block (such as the one above) as a script file by clicking the button which
appears in the top-right of the code block when you hover your mouse over it.

Table of Contents

Create a Script

Edit a Script

Run a Script

Tray Icon

Main Window

Command Line Usage
Portability of AutoHotkey.exe
Installer Options

Run with UI Access
Create a Script

There are a couple of common ways to create a script file:

In Notepad (or a text editor of your choice), save a file with the .ahk filename extension. On some systems you may need to

enclose the name in quotes to ensure the editor does not add another extension (such as .txt).

Be sure to save the file as UTF-8 with BOM if it will contain non-ASCII characters. For details, see the FAQ.

In Explorer, right-click in empty space in the folder where you want to save the script, then select New and AutoHotkey Script.
You can then type a name for the script (taking care not to erase the .ahk extension if it is visible).

See Scripting Language for details about how to write a script.
Edit a Script

To open a script for editing, right-click on the script file and select Edit Script. If the script is already running, you can use the Edit
command or right-click the script's tray icon and select Edit This Script. By default this will open Notepad, but that can be changed by writing to the registry as shown here. Of course, you can always open your text editor first and then open the script as you would any
other text file.

After editing a script, you must run or reload the script for the changes to take effect. A running script can usually be reloaded via its tray menu.

Run a Script

With AutoHotkey installed, there are several ways to run a script:
Double-click a script file (or shortcut to a script file) in Explorer.

Call AutoHotkey.exe on the command line and pass the script's filename as a command-line parameter.

After creating the default script, launch AutoHotkey via the shortcut in the Start menu to run it.

If AutoHotkey is pinned to the taskbar or Start menu on Windows 7 or later, recent or pinned scripts can be launched via the
program's Jump List.

Most scripts have an effect only while they are running. Use the tray menu or the ExitApp command to exit a script. Scripts are also
forced to exit when Windows shuts down. To configure a script to start automatically after the user logs in, the easiest way is to place a
shortcut to the script file in the Startup folder.


Scripts can also be compiled; that is, combined together with an AutoHotkey binary file to form a self-contained executable (.exe) file.
Tray Icon

By default, each script adds its own icon to the taskbar notification area (commonly known as the tray).

The tray icon usually looks like this (but the color or letter changes when the script is paused or suspended): 
Right-click the tray icon to show the tray menu, which has the following options by default:

Open - Open the script's main window.

Help - Open the AutoHotkey offline help file.

Window Spy - Displays various information about a window.
Reload This Script - See Reload.

Edit This Script - See Edit.

Suspend Hotkeys - Suspend or unsuspend hotkeys.

Pause Script - Pause or unpause the script.

Exit - Exit the script.

By default, double-clicking the tray icon shows the script's main window.
The Menu command can be used to customise the tray icon and menu.
The #NoTrayIcon directive can be used to hide the tray icon.

Main Window

The script's main window is usually hidden, but can be shown via the tray icon or one of the commands listed below to gain access to
information useful for debugging the script. Items under the View menu control what the main window displays:

Lines most recently executed - See ListLines.
Variables and their contents - See ListVars.
Hotkeys and their methods - See ListHotkeys.
Key history and script info - See KeyHistory.

Known issue: Keyboard shortcuts for menu items do not work while the script is displaying a MsgBox or other dialog.

The built-in variable A_ScriptHwnd contains the unique ID (HWND) of the script's main window.

Closing this window with WinClose (even from another script) causes the script to exit, but most other methods just hide the window
and leave the script running.

Command Line Usage

See Passing Command Line Parameters to a Script for command line usage, including a list of command line switches which affect the program's behavior.

Portability of AutoHotkey.exe

The file AutoHotkey.exe is all that is needed to launch any .ahk script.

[AHK_L 51+]: Renaming AutoHotkey.exe also changes which script it runs by default, which can be an alternative to compiling a script for use on a computer without AutoHotkey installed. For instance, MyScript.exe automatically runs MyScript.ahk if a filename is not
supplied, but is also capable of running other scripts.

Installer Options

To silently install AutoHotkey into the default directory (which is the same directory displayed by non-silent mode), pass the parameter /S to the installer. For example:

AutoHotkey110800_Install.exe /S

A directory other than the default may be specified via the /D parameter (in the absence of /S, this changes the default directory
displayed by the installer). For example:

AutoHotkey110800_Install.exe /S /D=C:\Program Files\AutoHotkey

Version: If AutoHotkey was previously installed, the installer automatically detects which version of AutoHotkey.exe to set as the
default. Otherwise, the default is Unicode 32-bit or Unicode 64-bit depending on whether the OS is 64-bit. To override which version of


AutoHotkey.exe is set as the default, pass one of the following switches:
/A32 or /ANSI: ANSI 32-bit.

/U64 or /x64: Unicode 64-bit (only valid on 64-bit systems).
/U32: Unicode 32-bit.

For example, the following installs silently and sets ANSI 32-bit as the default:

AutoHotkey110800_Install.exe /S /A32

Uninstall: To silently uninstall AutoHotkey, pass the /Uninstall parameter to Installer.ahk. For example:

"C:\Program Files\AutoHotkey\AutoHotkey.exe" "C:\Program Files\AutoHotkey\Installer.ahk" /Uninstall
For AutoHotkey versions older than 1.1.08.00, use uninst.exe /S. For example:

"C:\Program Files\AutoHotkey\uninst.exe" /S

Note: Installer.ahk must be run as admin to work correctly.

Extract: Later versions of the installer include a link in the bottom-right corner to extract setup files without installing. If this function is present, the /E switch can be used to invoke it from the command line. For example:

AutoHotkey110903_Install.exe /D=F:\AutoHotkey /E

Restart scripts [v1.1.19.02+]: In silent install/uninstall mode, running scripts are closed automatically, where necessary. Pass the /R
switch to automatically reload these scripts using whichever EXE they were running on, without command line args. Setup will attempt to launch the scripts via Explorer, so they do not run as administrator if UAC is enabled.

Taskbar buttons [v1.1.08+]: On Windows 7 and later, taskbar buttons for multiple scripts are automatically grouped together or
combined into one button by default. The Separate taskbar buttons option disables this by registering each AutoHotkey executable as a host app (IsHostApp).

[v1.1.24.02+]: For command-line installations, specify /IsHostApp or /IsHostApp=1 to enable the option and /IsHostApp=0 to disable

it.

Run with UI Access [v1.1.24.02+]

The installer GUI has an option "Add 'Run with UI Access' to context menus". This context menu option provides a workaround for
common UAC-related issues by allowing the script to automate administrative programs - without the script running as admin. To
achieve this, the installer does the following:

Copies AutoHotkeyA32.exe, AutoHotkeyU32.exe and (if present) AutoHotkeyU64.exe to AutoHotkey*_UIA.exe.
Sets the uiAccess attribute in each UIA file's embedded manifest.

Creates a self-signed digital certificate named "AutoHotkey" and signs each UIA file.

Registers the context menu option to run the appropriate exe file.

If any these UIA files are present before installation, the installer will automatically update them even if the UI Access option is not
enabled.

For command-line installations, specify /uiAccess or /uiAccess=1 to enable the option and /uiAccess=0 to disable it. By default, the installer will enable the option if UAC is enabled and the UI Access context menu option was present before installation.

Scripts which need to run other scripts with UI access can simply Run the appropriate UIA.exe file with the normal command line
parameters.

Known limitations:

UIA is only effective if the file is in a trusted location; i.e. a Program Files sub-directory.

UIA.exe files created on one computer cannot run on other computers without first installing the digital certificate which was used
to sign them.

UIA.exe files cannot be started via CreateProcess due to security restrictions. ShellExecute can be used instead. Run tries both.
UIA.exe files cannot be modified, as it would invalidate the file's digital signature.

Because UIA programs run at a different "integrity level" than other programs, they can only access objects registered by other
UIA programs. For example, ComObjActive("Word.Application") will fail because Word is not marked for UI Access.

The script's own windows can't be automated by non-UIA programs/scripts for security reasons.

Running a non-UIA script which uses a mouse hook (even as simple as #InstallMouseHook) may prevent all mouse hotkeys from
working when the mouse is pointing at a window owned by a UIA script, even hotkeys implemented by the UIA script itself. A
workaround is to ensure UIA scripts are loaded last.

For more details, see Enable interaction with administrative programs on the archive forum.


Scripts

Related topics:

Using the Program: How to use AutoHotkey, in general.

Concepts and Conventions: General explanation of various concepts utilised by AutoHotkey.
Scripting Language: Specific details about syntax (how to write scripts).

Table of Contents

Introduction

The Top of the Script (the Auto-execute Section): This portion executes automatically when the script starts.
Splitting a Long Line into a Series of Shorter Ones: This can improve a script's readability and maintainability.
Convert a Script to an EXE (ahk2exe): Convert a .ahk script into a .exe file that can run on any PC.

Passing Command Line Parameters to a Script: The variables %1%, %2%, etc. contain the incoming parameters.
Script File Codepage: Using non-ASCII characters safely in scripts.

Debugging a Script: How to find the flaws in a misbehaving script.

Introduction

Each script is a plain text file containing lines to be executed by the program (AutoHotkey.exe). A script may also contain hotkeys and hotstrings, or even
consist entirely of them. However, in the absence of hotkeys and hotstrings, a script will perform its commands sequentially from top to bottom the moment it is launched.

The program loads the script into memory line by line, and each line may be up to 16,383 characters long. During loading, the script is optimized and
validated. Any syntax errors will be displayed, and they must be corrected before the script can run.

The Top of the Script (the Auto-execute Section)

After the script has been loaded, it begins executing at the top line, continuing until a Return, Exit, hotkey/hotstring label, or the physical end of the script is encountered (whichever comes first). This top portion of the script is referred to as the auto-execute section.

Note: While the script's first hotkey/hotstring label has the same effect as return, other hotkeys and labels do not.

A script that is not persistent and that lacks hotkeys, hotstrings, OnMessage, and GUI will terminate after the auto-execute section has completed. Otherwise, it will stay running in an idle state, responding to events such as hotkeys, hotstrings, GUI events, custom menu items, and timers.

Every thread launched by a hotkey, hotstring, menu item, GUI event, or timer starts off fresh with the default values for the following attributes as set in the auto-execute section. If unset, the standard defaults will apply (as documented on each of the following pages): DetectHiddenWindows, DetectHiddenText,
SetTitleMatchMode, SetBatchLines, SendMode, SetKeyDelay, SetMouseDelay, SetWinDelay, SetControlDelay, SetDefaultMouseSpeed, CoordMode,

SetStoreCapsLockMode, AutoTrim, SetFormat, StringCaseSense, Thread, and Critical.

If the auto-execute section takes a long time to complete (or never completes), the default values for the above settings will be put into effect after 100
milliseconds. When the auto-execute section finally completes (if ever), the defaults are updated again to be those that were in effect at the end of the auto-
execute section. Thus, it's usually best to make any desired changes to the defaults at the top of scripts that contain hotkeys, hotstrings, timers, or custom
menu items. Also note that each thread retains its own collection of the above settings. Changes made to those settings will not affect other threads.

Splitting a Long Line into a Series of Shorter Ones

Long lines can be divided up into a collection of smaller ones to improve readability and maintainability. This does not reduce the script's execution speed
because such lines are merged in memory the moment the script launches.

Method #1: A line that starts with "and", "or", ||, &&, a comma, or a period is automatically merged with the line directly above it (in v1.0.46+, the same is
true for all other expression operators except ++ and --). In the following example, the second line is appended to the first because it begins with a comma:

FileAppend, This is the text to append.`n   ; A comment is allowed here.
    , %A_ProgramFiles%\SomeApplication\LogFile.txt  ; Comment.

Similarly, the following lines would get merged into a single line because the last two start with "and" or "or":

if (Color = "Red" or Color = "Green"  or Color = "Blue"   ; Comment.
    or Color = "Black" or Color = "Gray" or Color = "White")   ; Comment.
    and ProductIsAvailableInColor(Product, Color)   ; Comment.

The ternary operator is also a good candidate:

ProductIsAvailable := (Color = "Red")

    ? false  ; We don't have any red products, so don't bother calling the function.
    : ProductIsAvailableInColor(Product, Color)

Although the indentation used in the examples above is optional, it might improve clarity by indicating which lines belong to ones above them. Also, it is not necessary to include extra spaces for lines starting with the words "AND" and "OR"; the program does this automatically. Finally, blank lines or comments
may be added between or at the end of any of the lines in the above examples.

Method #2: This method should be used to merge a large number of lines or when the lines are not suitable for Method #1. Although this method is
especially useful for auto-replace hotstrings, it can also be used with any command or expression. For example:

; EXAMPLE #1:
Var =

(

Line 1 of the text.


Line 2 of the text. By default, a linefeed (`n) is present between lines.

)

; EXAMPLE #2:

FileAppend,  ; The comma is required in this case.

(

A line of text.

By default, the hard carriage return (Enter) between the previous line and this one will be written to the file as a linefeed (`n).     By default, the tab to the left of this line will also be written to the file (the same is true for spaces).

By default, variable references such as %Var% are resolved to the variable's contents.

), C:\My File.txt

In the examples above, a series of lines is bounded at the top and bottom by a pair of parentheses. This is known as a continuation section. Notice that the
bottom line contains FileAppend's last parameter after the closing parenthesis. This practice is optional; it is done in cases like this so that the comma will be
seen as a parameter-delimiter rather than a literal comma.

The default behavior of a continuation section can be overridden by including one or more of the following options to the right of the section's opening
parenthesis. If more than one option is present, separate each one from the previous with a space. For example: ( LTrim Join| %.

Join: Specifies how lines should be connected together. If this option is omitted, each line except the last will be followed by a linefeed character (`n). If the
word Join is specified by itself, lines are connected directly to each other without any characters in between. Otherwise, the word Join should be followed
immediately by as many as 15 characters. For example, Join`s would insert a space after each line except the last ("`s" indicates a literal space -- it is a
special escape sequence recognized only by Join). Another example is Join`r`n, which inserts CR+LF between lines. Similarly, Join| inserts a pipe
between lines. To have the final line in the section also ended by a join-string, include a blank line immediately above the section's closing parenthesis.

Known limitation: If the Join string ends with a colon, it must not be the last option on the line. For example, (Join: is treated as the label "(Join" and
(LTrim Join: is unsupported, but (Join: C is okay.

LTrim: Omits spaces and tabs at the beginning of each line. This is primarily used to allow the continuation section to be indented. Also, this option may be
turned on for multiple continuation sections by specifying #LTrim on a line by itself. #LTrim is positional: it affects all continuation sections physically
beneath it. The setting may be turned off via #LTrim Off.

RTrim0 (RTrim followed by a zero): Turns off the omission of spaces and tabs from the end of each line.

Comments (or Comment or Com or C) [v1.0.45.03+]: Allows semicolon comments inside the continuation section (but not /*..*/). Such comments (along with any spaces and tabs to their left) are entirely omitted from the joined result rather than being treated as literal text. Each comment can appear to the right of a line or on a new line by itself.

% (percent sign): Treats percent signs as literal rather than as variable references. This avoids the need to escape each percent sign to make it literal. This
option is not needed in places where percent signs are already literal, such as auto-replace hotstrings.

, (comma): Treats commas as delimiters rather than as literal commas. This rarely-used option is necessary only for the commas between command
parameters because in function calls, the type of comma does not matter. Also, this option transforms only those commas that actually delimit parameters. In
other words, once the command's final parameter is reached (or there are no parameters), subsequent commas are treated as literal commas regardless of this
option.

` (accent): Treats each backtick character literally rather than as an escape character. This also prevents commas and percent signs from being explicitly and
individually escaped. In addition, it prevents the translation of any explicitly specified escape sequences such as `r and `t.

) [v1.1.01+]: If a closing parenthesis appears in the continuation section's options (except as a parameter of the Join option), the line is reinterpreted as an
expression instead of the beginning of a continuation section. This allows expressions like (x.y)[z]() to work without the need to escape the opening
parenthesis.

Remarks

Escape sequences such as `n (linefeed) and `t (tab) are supported inside the continuation section except when the accent (`) option has been specified.
When the comment option is absent, semicolon and /*..*/ comments are not supported within the interior of a continuation section because they are seen as
literal text. However, comments can be included on the bottom and top lines of the section. For example:

FileAppend,   ; Comment.

; Comment.

( LTrim Join    ; Comment.

     ; This is not a comment; it is literal. Include the word Comments in the line above to make it a comment.
), C:\File.txt   ; Comment.

As a consequence of the above, semicolons never need to be escaped within a continuation section.

A continuation section cannot produce a line whose total length is greater than 16,383 characters (if it tries, the program will alert you the moment the script
is launched). One way to work around this is to do a series of concatenations into a variable. For example:

Var =

(

...

)

Var = %Var%`n  ; Add more text to the variable via another continuation section.

(

...

)

FileAppend, %Var%, C:\My File.txt

Since a closing parenthesis indicates the end of a continuation section, to have a line start with literal closing parenthesis, precede it with an accent/backtick:
`).

A continuation section can be immediately followed by a line containing the open-parenthesis of another continuation section. This allows the options
mentioned above to be varied during the course of building a single line.


The piecemeal construction of a continuation section by means of #Include is not supported.
Convert a Script to an EXE (ahk2exe)

A script compiler (courtesy of fincs) is included with the program.

Once a script is compiled, it becomes a standalone executable; that is, AutoHotkey.exe is not required in order to run the script. The compilation process
creates an executable file which contains the following: the AutoHotkey interpreter, the script, any files it includes, and any files it has incorporated via the
FileInstall command.

Ahk2Exe can be used in the following ways:

1. GUI Interface: Run the "Convert .ahk to .exe" item in the Start Menu.

2. Right-click: Within an open Explorer window, you can right-click any .ahk file and select "Compile Script" (only available if the script compiler
option was chosen when AutoHotkey was installed). This creates an EXE file of the same base filename as the script, which appears after a short time

in the same directory. Note: The EXE file is produced using the same custom icon, .bin file and use MPRESS setting that were last used by Method #1
above.

3. Command Line: The compiler can be run from the command line with the following parameters:

Ahk2Exe.exe /in MyScript.ahk [/out MyScript.exe] [/icon MyIcon.ico] [/bin AutoHotkeySC.bin] [/mpress 0or1]
For example:

Ahk2Exe.exe /in "MyScript.ahk" /icon "MyIcon.ico"
Usage:

Parameters containing spaces should be enclosed in double quotes.

If the "out" file is omitted, the EXE will have the same base filename as the script itself.

Notes:

Compiling does not typically improve the performance of a script.

As of v1.1.01, password protection and the /NoDecompile switch are not supported.

The commands #NoTrayIcon and "Menu, Tray, ShowMainWindow" affect the behavior of compiled scripts.

Custom version info (as seen in Explorer's file-properties dialog) can be added to your compiled scripts by using a utility such as Resource Hacker
(freeware) to edit the file "AutoHotkeySC.bin". This file is contained in the "Compiler" subfolder where AutoHotkey was installed. Compile_AHK II
can be used to facilitate this process. As of v1.1.01, the compiled script can be edited instead of AutoHotkeySC.bin.

The method above can also be used to change existing icons or add new ones to all compiled scripts.

The built-in variable A_IsCompiled contains 1 if the script is running in compiled form. Otherwise, it is blank.

When parameters are passed to Ahk2Exe, a message indicating the success or failure of the compiling process is written to stdout. Although the
message will not appear at the command prompt, it can be "caught" by means such as redirecting output to a file. [v1.0.43+]

Additionally in the case of a failure, Ahk2Exe has exit codes indicating the kind of error that occurred. These error codes can be found at GitHub
(ErrorCodes.md). [v1.1.22.03+]

The compiler's source code and newer versions can be found at GitHub.
Compressing Compiled Scripts

Ahk2Exe optionally uses MPRESS (a freeware program by MATCODE Software) to compress compiled scripts. If mpress.exe is present in the "Compiler" subfolder where AutoHotkey was installed, it is used automatically unless it is disabled via /mpress 0 or the GUI setting.

Official website (was offline in March 2016): http://www.matcode.com/mpress.htm

Mirror (downloads and information): https://autohotkey.com/mpress/

Note: While compressing the script executable prevents casual inspection of the script's source code using a plain text editor like Notepad or a PE resource
editor, it does not prevent the source code from being extracted by tools dedicated to that purpose.

Passing Command Line Parameters to a Script

Scripts support command line parameters. The format is:

AutoHotkey.exe [Switches] [Script Filename] [Script Parameters]
And for compiled scripts, the format is:

CompiledScript.exe [Switches] [Script Parameters]
Switches: Zero or more of the following:

Switch                                                                                           Meaning Works 
compiled?

/f or /forceLaunch unconditionally, skipping any warning dialogs. This has the same effect as #SingleInstance Off.                                                                                                                                                                      Yes
/r or /restartIndicate that the script is being restarted (this is also used by the Reload command, internally).                                                                                                                                                                      Yes
/ErrorStdOutSend syntax errors that prevent a script from launching to stderr rather than displaying a dialog. See #ErrorStdOut for details. This 


 

 

 

/iLib
"OutFile"


[v1.0.47+]: AutoHotkey loads the script but does not run it. For each script file which is auto-included via the library mechanism, two lines are written to the file specified by OutFile. These lines are written in the following format, where LibDir is the full path of the Lib folder and LibFile is the filename of the library:

#Include LibDir\

#IncludeAgain LibDir\LibFile.ahk

If the output file exists, it is overwritten. OutFile can be * to write the output to stdout.

If the script contains syntax errors, the output file may be empty. The process exit code can be used to detect this condition; if there is a syntax error, the exit code is 2. The /ErrorStdOut switch can be used to suppress or capture the error message.


 

 

 

No


 

Script Filename: This can be omitted if there are no Script Parameters. If omitted (such as if you run AutoHotkey directly from the Start menu), the
program looks for a script file called AutoHotkey.ahk in the following locations, in this order:

The directory which contains the AutoHotkey executable.
The current user's Documents folder.

The filename AutoHotkey.ahk depends on the name of the executable used to run the script. For example, if you rename AutoHotkey.exe to MyScript.exe, it will attempt to find MyScript.ahk. If you run AutoHotkeyU32.exe without parameters, it will look for AutoHotkeyU32.ahk.

Note: In old versions prior to revision 51, the program looked for AutoHotkey.ini in the working directory or AutoHotkey.ahk in My Documents.
[v1.1.17+]: Specify an asterisk (*) for the filename to read the script text from standard input (stdin). For an example, see ExecScript().

Script Parameters: The string(s) you want to pass into the script, with each separated from the next by a space. Any parameter that contains spaces should
be enclosed in quotation marks. A literal quotation mark may be passed in by preceding it with a backslash (\"). Consequently, any trailing slash in a quoted parameter (such as "C:\My Documents\") is treated as a literal quotation mark (that is, the script would receive the string C:\My Documents"). To remove
such quotes, use StringReplace, 1, 1, ",, All.

[v1.1.27+]: Incoming parameters, if present, are stored as an array in the built-in variable A_Args, and can be accessed using array syntax. A_Args[1]
contains the first parameter. The following example exits the script when too few parameters are passed to it:

if A_Args.Length() < 3

{

    MsgBox % "This script requires at least 3 parameters but it only received " A_Args.Length() "."
    ExitApp

}

If the number of parameters passed into a script varies (perhaps due to the user dragging and dropping a set of files onto a script), the following example can be used to extract them one by one:

for n, param in A_Args  ; For each parameter:

{

    MsgBox Parameter number %n% is %param%.

}

If the parameters are file names, the following example can be used to convert them to their case-corrected long names (as stored in the file system), including complete/absolute path:

for n, GivenPath in A_Args  ; For each parameter (or file dropped onto a script):

{

    Loop Files, %GivenPath%, FD  ; Include files and directories.

        LongPath := A_LoopFileFullPath

    MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath%

}

Known limitation: dragging files onto a .ahk script may fail to work properly if 8-dot-3 (short) names have been turned off in an NTFS file system. One
work-around is to compile the script then drag the files onto the resulting EXE.

Legacy: The command line parameters are also stored in the variables %1%, %2%, and so on, as in versions prior to [v1.1.27]. In addition, %0% contains the number of parameters passed (0 if none). However, these variables cannot be referenced directly in an expression because they would be seen as numbers
rather than variables. The following example exits the script when too few parameters are passed to it:

if 0 < 3  ; The left side of a non-expression if-statement is always the name of a variable.

{

    MsgBox This script requires at least 3 incoming parameters but it only received %0%.
    ExitApp

}

If the number of parameters passed into a script varies (perhaps due to the user dragging and dropping a set of files onto a script), the following example can be used to extract them one by one:

Loop, %0%  ; For each parameter:

{

    param := %A_Index%  ; Fetch the contents of the variable whose name is contained in A_Index.
    MsgBox, 4,, Parameter number %A_Index% is %param%.  Continue?

    IfMsgBox, No

        break

}

If the parameters are file names, the following example can be used to convert them to their case-corrected long names (as stored in the file system), including complete/absolute path:

Loop %0%  ; For each parameter (or file dropped onto a script):

{

    GivenPath := %A_Index%  ; Fetch the contents of the variable whose name is contained in A_Index.


    Loop %GivenPath%, 1

        LongPath = %A_LoopFileLongPath%

    MsgBox The case-corrected long path name of file`n%GivenPath%`nis:`n%LongPath%

}

Script File Codepage [AHK_L 51+]

The characters a script file may contain are restricted by the codepage used to load the file.

If the file begins with a UTF-8 or UTF-16 (LE) byte order mark, the appropriate codepage is used and the /CPn switch is ignored.

If the /CPn switch is passed on the command-line, codepage n is used. For a list of valid numeric codepage identifiers, see MSDN.
In all other cases, the system default ANSI codepage is used.

Note that this applies only to script files loaded by AutoHotkey, not to file I/O within the script itself. FileEncoding controls the default encoding of files read or written by the script, while IniRead and IniWrite always deal in UTF-16 or ANSI.

As all text is converted (where necessary) to the native string format, characters which are invalid or don't exist in the native codepage are replaced with a
placeholder: ANSI '?' or Unicode ''. In Unicode builds, this should only occur if there are encoding errors in the script file or the codepages used to save and load the file don't match.

RegWrite may be used to set the default for scripts launched from Explorer (e.g. by double-clicking a file):

; Uncomment the appropriate line below or leave them all commented to
;   reset to the default of the current build.  Modify as necessary:
; codepage = 0        ; System default ANSI codepage

; codepage = 65001    ; UTF-8

; codepage = 1200     ; UTF-16

; codepage = 1252     ; ANSI Latin 1; Western European (Windows)

if (codepage != "")

    codepage := " /CP" . codepage

cmd="%A_AhkPath%"%codepage% "`%1" `%*
key=AutoHotkeyScript\Shell\Open\Command

if A_IsAdmin    ; Set for all users.

    RegWrite, REG_SZ, HKCR, %key%,, %cmd%

else            ; Set for current user only.

    RegWrite, REG_SZ, HKCU, Software\Classes\%key%,, %cmd%

This assumes AutoHotkey has already been installed. Results may be less than ideal if it has not.
Debugging a Script

Commands such as ListVars and Pause can help you debug a script. For example, the following two lines, when temporarily inserted at carefully chosen
positions, create "break points" in the script:

ListVars
Pause

When the script encounters these two lines, it will display the current contents of all variables for your inspection. When you're ready to resume, un-pause the script via the File or Tray menu. The script will then continue until reaching the next "break point" (if any).

It is generally best to insert these "break points" at positions where the active window does not matter to the script, such as immediately before a WinActivate command. This allows the script to properly resume operation when you un-pause it.

The following commands are also useful for debugging: ListLines, KeyHistory, and OutputDebug.

Some common errors, such as typos and missing "global" declarations, can be detected by enabling warnings.
Interactive Debugging [AHK_L 11+]

Interactive debugging is possible with a supported DBGp client. Typically the following actions are possible:
Set and remove breakpoints on lines - pause execution when a breakpoint is reached.

Step through code line by line - step into, over or out of functions and subroutines.
Inspect all variables or a specific variable.

View the stack of running subroutines and functions.

Note that this functionality is disabled for compiled scripts.

To enable interactive debugging, first launch a supported debugger client then launch the script with the /Debug command-line switch.

AutoHotkey.exe /Debug=SERVER:PORT ...

SERVER and PORT may be omitted. For example, the following are equivalent:

AutoHotkey /Debug "myscript.ahk"

AutoHotkey /Debug=localhost:9000 "myscript.ahk"

[AHK_L 59+]: To attach the debugger to a script which is already running, send it a message as shown below:

ScriptPath = ; SET THIS TO THE FULL PATH OF THE SCRIPT

DetectHiddenWindows On

IfWinExist %ScriptPath% ahk_class AutoHotkey

    ; Optional parameters:

    ;   wParam  = the IPv4 address of the debugger client, as a 32-bit integer.
    ;   lParam  = the port which the debugger client is listening on.
    PostMessage DllCall("RegisterWindowMessage", "str", "AHK_ATTACH_DEBUGGER")


Once the debugger client is connected, it may detach without terminating the script by sending the "detach" DBGp command. Script Showcase

See this page for some useful scripts.


Changes & New Features

Changes and new features introduced by the current branch of AutoHotkey development (a.k.a. AutoHotkey_L) are listed below.
For older changes, see Archived Changes.

1.1.30.00 - August 22, 2018

Fixed SendInput/SendPlay to restore DownR/remapped modifiers.

Increased limit of hotkeys per script from 1000 to 32762.

Changed commands which accept On/Off/Toggle to also accept 1/0/-1 (where documented).
Improvements to debugger (DBGp) support:

Added support for the -d (stack depth) option.

Added (DBGp-only) .<base> pseudo-property to resolve ambiguity.
Fixed debugger to avoid unsupported re-entry during break state.
Fixed DBGp command parser to support quoted parameters.

1.1.29.01 - June 2, 2018

Fixed WinMove crashing the program in some cases [broken by v1.1.29.00].
Fixed Gui x:Default if no Gui has been created [broken by v1.1.29.00].
1.1.29.00 - May 25, 2018

Added Object.Count() and ObjCount(Object).

Added ObjGetBase(Object) and ObjSetBase(Object, Base).
Added ObjRawGet(Object, Key).

Added OnError(Func [, AddRemove]).

Revised exception handling:

If unhandled, show an error message/call OnError before the stack unwinds (making exceptions consistent with runtime errors).
Fixed __Delete causing commands to throw even when Try is not used.

Fixed COM clients unable to catch built-in script errors.

Removed the limits on the number of custom modifiers that can be used with each key.

Changed Send {Text} to avoid toggling CapsLock or waiting for Win+L.

Fixed #Warn ClassOverwrite to not warn for A_Args.

Improved DBGp source command to properly convert between file codepage and UTF-8, and to reduce code size.
Other code size optimizations and trivial maintenance.

1.1.28.02 - April 7, 2018

Fixed Control ChooseString and ControlGet FindString ignoring the first two items.
Fixed Control ChooseString to send WM_COMMAND even if the control's ID is 0.
Fixed WinActivate to restore the active window, as originally intended for [v1.1.20.00].
1.1.28.01 - March 31, 2018

Fixed Thread treating omitted parameters as 0.

Fixed FileAppend to stderr (**).

Fixed break label being able to jump to an unrelated loop.


Reverted hotstring reset behaviour to pre-v1.1.28.00.

Added Hotstring("Reset") for manually resetting the hotstring recognizer.
1.1.28.00 - February 11, 2018

Changes:

Changed __Delete to catch and report exceptions when called during object cleanup. It previously had the (erroneous) effect of

"postponing" the exception until the next function call or the end of the try-block/thread.

Changed hotstring recognizer to reset when focus changes instead of just when the active window changes.
Changed WinMenuSelectItem to treat menu 0& as the window's system menu.

New features:

Added support for all built-in variables in the path passed to #Include.

Added A_TimeIdleKeyboard and A_TimeIdleMouse.

Added A_ListLines.

Added A_ComSpec (alias of ComSpec).

Added A_LoopFilePath (alias of A_LoopFileFullPath, which is a misnomer).
Added hotstring X option to execute a same-line action instead of auto-replace.
Added Hotstring().

Added function hotstrings.

Added MaxParts parameter to StrSplit.

Improved #MenuMaskKey to allow specifying VK and SC, or vk00sc000.

Bug fixes:

Fixed #MenuMaskKey treating some valid keys (such as Del) as invalid.

Optimised detection of AltGr on Unicode builds. This fixes a delay which occurred at startup (since v1.1.27.00) or the first time
Send is called for each target keyboard layout (prior to v1.1.27.00).

Fixed misleading vicinity lines for x up::y remap error.

Fixed Menu Tray, Icon, HICON:%hicon%, which now uses hicon without resizing it.

1.1.27.07 - January 21, 2018

Fixed default size of Gui with +Parent to not be restricted by parent [broken by v1.1.27.05].

Fixed controls not redrawing if a separate Tab control is shown/hidden immediately after the control was invalidated (such as when
showing/hiding multiple controls at once).

1.1.27.06 - January 16, 2018

Fixed hotstrings/Input causing stuck dead keys (broken by v1.1.27.05).
1.1.27.05 - January 16, 2018

Fixed visible Input end keys causing any pending dead key to double up.
Fixed hotstrings/Input affecting how Tab/Esc act in a dead key sequence.
Fixed A_IconFile returning an incorrect path if a DLL was used.

Fixed Gui with +Parent to center within the parent GUI vs. the screen.

Fixed Input/hotstring detection of dead key sequences in Universal Windows Platform (UWP) apps.

Fixed < & v and > & v being seen as duplicates, and similar cases. This affects custom combinations where the prefix key is also a
modifier symbol. This also fixes hotkeys which consist only of modifier symbols and a single trailing space, such as + ::, to be treated as errors rather than ignoring the space (hotkeys do not permit trailing space).

1.1.27.04 - January 10, 2018

Fixed #Warn ClassOverwrite giving erroneous warnings.
1.1.27.03 - January 6, 2018


Improved Menu x, NoStandard and Menu x, DeleteAll to work without attempting to destroy the underlying Win32 menu. This
allows them to work when x is a menu bar or sub-menu of one.

Reworked the handling of vkXXscYYY:

Fixed GetKeyVK and GetKeyName treating vkXXscYYY as vk00scYYY.

Send is now more strict with {vk...} and invalid suffixes, consistent with similar changes made by [v1.1.27.00] (but sc is still
supported).

Reduced code size.

Fixed mishandling of numeric keys outside the 32-bit range (but inside the 64-bit range) in some corner cases on 64-bit builds. This only affects classes which use such numbers as names (not recommended for multiple reasons) and array access via IDispatch with such
numbers as keys/member names.

1.1.27.02 - January 1, 2018

Fixed loading of bmp files as icons at original size.

Fixed compound assignments such as Test.Prop[1] += 1 (broken by v1.1.27.01).
1.1.27.01 - December 31, 2017

Fixed program crashes caused by ++X or --X in scripts which lack #NoEnv (broken by v1.1.27.00).

Fixed #Warn ClassOverwrite giving an erroneous warning for ++MyClass.X.

Fixed remapping to allow custom combinations such as a & b::c.

Fixed Send/hotstrings/Input to adapt to the keyboard layout of the focused control instead of just the active window. In particular, this
affects UWP apps such as Microsoft Edge.

Fixed hook hotkeys to suppress the Start menu activation which occurs when an isolated Ctrl/Shift up is received. Ctrl up may be
generated by the system when switching from a keyboard layout with AltGr to one without (such as from UK to US), if Ctrl is not held down at the time. This fixes hotkeys such as $#z::WinActivate x when the change in focus causes those conditions.

Fixed Input not collecting characters when both Shift keys are down.

Fixed Input to use "sc" and "vk" for end keys in ErrorLevel rather than "Sc" and "Vk" (caused by v1.1.20).
Fixed GetKeyName/VK/SC("vkXXscYYY") where YYY begins with A-F (broken by v1.1.26).

1.1.27.00 - December 25, 2017

Changes:

Replaced AU3_Spy.exe with WindowSpy.ahk.

AU3_Spy.exe is still launched if WindowSpy.ahk is not found.

It now follows the focused control by default, and has a checkbox for both window and control to follow the mouse.

It no longer takes over a global hotkey (Win+A). Instead, hold Ctrl or Shift to suspend updates (release them after focusing
Window Spy).

It is now possible to Alt-Tab to Window Spy on Windows 10 without the contents of the GUI changing.

Changed a-z to mean vk41-vk5A when absent from the keyboard layout, except with Raw mode or when sending single unmodified
characters. This allows hotkeys and sent keyboard shortcuts to work more intuitively on certain non-English keyboard layouts.

Changed Send on ANSI versions to use SendInput() in place of Alt+nnnnn for special characters.
Changed the rules for masking Alt/Win after pressing a hook hotkey:

Explicitly sent Alt/Win up may be masked. This fixes remappings such as AppsKey::RWin, but hotkeys which are intended to
activate the Start Menu may require new workarounds.

If Alt/Win is logically but not physically down, only hotkeys which require Alt/Win (such as #a::, not *a::) cause masking. This
is to allow a remapping or wildcard hotkey to send the key-up without it being masked.

Unsuppressed hotkeys such as ~#a:: no longer cause masking, because the unsuppressed keydown/keyup is sufficient to prevent a
menu. However, mouse hotkeys like ~*MButton:: no longer suppress the Start Menu if combined with the Win key. It can be
suppressed manually with Send {Blind}{vk07} or similar.

The keyboard hook now tracks events in relation to Alt/Win, so that the mask key does not need to be sent if Alt/Win was already
masked by some other event (physical or sent).


The hotkeys ~LWin:: and ~RWin:: no longer suppress the Start Menu. See #MenuMaskKey for details and a workaround.

Added proper validation for vk or sc key names, so names such as "sc01notvalid" are no longer recognized as keys.

Scripts containing hotkeys of the form VKnnSCnnn:: will need to be corrected by removing SCnnn, which was previously ignored.
Help file: Replaced the standard HTML Help Viewer sidebar with the new HTML5 sidebar developed by Ragnar-F.

New features:

Added Min/Max built-in functions. [PR #84 from Ragnar-F]

Added A_Args as an alternative to the numbered variables.

Added force-local mode for functions.

Added #Warn ClassOverwrite.

Added {Text} mode for Send and T option for hotstrings. These are like the Raw mode, but more reliable.
Added {key DownR} and changed remapping to use it, to fix issues with AppsKey::RWin and similar.

Bug fixes:

Fixed icon-loading to not default to ID 0 when the index is invalid.

Fixed VK↔SC mapping of PrintScreen. SC→VK was already correct on Vista and later.

Fixed Hotkey control returning scXXX instead of names in some cases.

Fixed ListVars crashing if a ByRef parameter refers to a variable containing an object. [PR #86 from HotKeyIt]

Fixed some (very unlikely) memory leaks.

Fixed menu handles not being freed if only the standard items are used.

Fixed bold font not being applied to default menu item if it has a submenu and a Win32 menu handle.

Fixed Send to use the correct modifier state with Unicode chars.

Fixed ControlSend {u n}, where u is Unicode, to send n times, not just 1.

Fixed inconsistent behavior of AltGr between OS versions. Specifically, RAlt:: once again causes the system to "release" LCtrl on
Windows 10, as it did prior to v1.1.26.01 (but unlike those old versions, it prevents the RAlt-up from reaching the active window).
This change should not affect layouts without AltGr.

Fixed Menu Tray, Icon, SB_SetIcon and LoadPicture with non-zero Icon option to allow bitmaps (but convert if needed).

Fixed menu items to not disappear when a cursor is set as a menu item's icon.

Improved launching of Window Spy and the help file:

If AutoHotkey is installed but the current executable is in a different directory (i.e. portable), the installed file is no longer
preferred as it may be the wrong version. It may still be used as a fallback.

On failure to launch the file, show the error message inside the dialog, not in its titlebar.

Fixed one-line hotkeys with expressions beginning in sc or vk.

Fixed >/< hotkey modifiers incorrectly allowing both keys to be pressed. For example, <^A could erroneously be triggered by
LCtrl+RCtrl+A, thereby preventing the <>^A hotkey from working.

Fixed auto-replace hotstrings inserting the literal text "{Raw}" in some cases (specifically, when the replacement contains {Raw}
and the O, R and * options were not used).

Fixed some hotkeys not using the hook when eclipsed by a wildcard hotkey, depending on the order of definition.

Fixed key-down hotkeys to revert to "reg" if they were only "k-hook" because of a corresponding key-up hotkey which has since
been disabled. (Prior to v1.1.07.03 this already happened, but the key-down hotkey was never set to "k-hook" in the first place if
defined after the key-up.)

Fixed hook hotkeys to ignore modifier changes made by Send !^+#{key} or when sending Unicode characters. This restores Send
to how it was prior to v1.1.06 when at SendLevel 0, but keeps the v1.1.06+ behavior at SendLevel >= 1, allowing Send to trigger
the right hotkeys.

Improved the odds that Send from a "reg" hotkey such as ^m::Send x will restore the modifier state if Send is being called for the
very first time. This makes it less likely to produce a different (and unexpected) result the first time it is held down, such as xmmm
instead of xxxx.

1.1.26.01 - July 16, 2017

Fixed RegDelete (with no args) failing when A_LoopRegSubKey is blank, such as when enumerating keys directly under the root key.
Fixed RAlt/LAlt:: sometimes failing to prevent menu activation after the user alt-tabs away from a window and reactivates it.

Fixed SC → VK translation for multimedia keys, PrintScreen, CtrlBreak, Pause, LWin and RWin, with the exception that multimedia
keys, PrintScreen and CtrlBreak are still translated incorrectly on Windows 2000 and XP.

Fixed VK → SC translation for multimedia keys, CtrlBreak and Pause.

Fixed 'Wait commands such as RunWait to log extra lines for ListLines only when necessary to show that it is still waiting; that is, after resuming from an interruption which logged other lines.

1.1.26.00 - June 10, 2017


Changed the format ListVars uses to display variables containing objects. The object's class name is now shown.
Added "class" and "clsid" modes to ComObjType().

Revised class names shown by the debugger and significantly reduced code size in the process.

Revised FileSetAttrib, FileSetTime and FileDelete to reduce code size. There should not be any changes in behaviour.
Made other minor optimizations to code size.

Fixed GetKeySC() with the key names Esc, Escape, ScrollLock and PrintScreen.

Fixed hotstring word detection of words containing nonspacing marks, such as Arabic diacritics.

1.1.25.02 - May 13, 2017

Fixed GUI option strings being permanently truncated if an error is raised.
Fixed properties and class sub-variables to allow non-ASCII characters.
Fixed new operator to allow __New to throw or exit.

1.1.25.01 - March 5, 2017

Fixed Send to allow other scripts to act on modifier state changes which immediately precede a special character, such as the Shift
release in Send Mört.

1.1.25.00 - March 4, 2017

Added Hotkey, If, % FunctionObject.

Fixed website address in Help menu.
1.1.24.05 - February 3, 2017

Fixed WinSet AlwaysOnTop/Trans/TransColor to work on windows with 0 ExStyle.
1.1.24.04 - December 17, 2016

Fixed File.ReadNum() repeating old data if a prior File.Read() had stopped reading at the end of the buffer.
Improved buffer utilisation when File.Read() reaches the end of the buffered data.

Fixed GuiControl +Password to use the default bullet character on XP and later.

Fixed GuiControl +/-Password to redraw the control immediately.

1.1.24.03 - November 19, 2016

Fixed COM exception messages to not end in `r.

Fixed {U+x} to support supplementary characters (x > 0xFFFF).

Fixed class properties which lack get{} to return an empty value instead of the internal Property object when the class has a base which
does not define a value for the property. Properties defined in baseless classes already behaved correctly.

Fixed the background color of controls on a Tab3 control when the system has visual styles disabled (i.e. Windows Classic).

Fixed handling of thread-exit in functions which are called directly by an event (such as OnExit functions). This bug had no known effect except in the v2-alpha branch.

Fixed the debugger to detect disconnection immediately (i.e. when a client terminates without calling stop/detach).
Fixed the debugger to treat property_get -m 0 as "unlimited", as per the DBGp spec.

Fixed the debugger to expect base64 for property_set -t integer/float, as per the DBGp spec.

1.1.24.02 - October 13, 2016


Added a Run with UI Access option to the installer.
Added documentation for Tab3 autosizing.

Fixed several Tab3 bugs:

Autosizing was not being triggered by the first call to Gui Show if the AutoSize or w and h options were used.
If a Tab3 control is empty when autosizing occurs, it now retains the default size instead of becoming unusable.
Autosizing now occurs immediately before creating another tab control, as though Gui Tab was called.
Autosizing failed if the tab control had negative screen coords.

Hiding a Tab3 control with GuiControl now also hides its dialog/background.

Fixed OnMessage to pass lParam as unsigned on 32-bit.

Fixed Gui Name : to allow spaces before the colon.

Fixed identifying a Gui or GuiControl by HWND with a negative value.

Fixed ComObject to suppress any errors raised by disconnection of events after the script has released the object.
Fixed Gui Show causing the window to shrink if it had a multi-line menu bar.

Fixed LV_InsertCol(n, width) not causing ListView scrollbar to update on some OS versions.

Optimized code size of FileRecycleEmpty.

1.1.24.01 - August 2, 2016

Changed Hotkey, If, Expression to raise an error if the unused third parameter is not blank.
Fixed &&, || and ternary to release any object used as the condition, as in if (a.subObject && b).
Fixed Gui/GuiControl failing to "check" radio buttons within a Tab3 control.

Fixed FileCreateShortcut to allow relative paths for the LinkFile parameter on Windows 10.

Fixed themed Tab3 control to not override the custom text color of its controls.

Fixed debugger mishandling continuation commands in some specific cases.

1.1.24.00 - May 22, 2016

Breaking changes:

Passing SetTimer's Label parameter an empty variable or an expression which results in an empty value is now considered an error. The parameter must be either given a non-empty value or completely omitted.

Run-once timers are automatically deleted after running if they are associated with an object created by the script. This allows the object to be freed if the script is no longer referencing it, but it also means the timer's Period and Priority are not retained.

SetTimer, Hotkey, GuiControl and Menu now check the minimum parameter count of functions given by reference (not just by name, as in previous versions). If the function requires too many parameters, an error is raised or ErrorLevel is set (as appropriate).

Backward-compatible changes:

If SetTimer's Label parameter is omitted and A_ThisLabel is empty, the current timer (if any) is used.
New features:

Added Tab3 control type, solving a number of issues with Tab controls.

Bug-fixes:

Fixed GuiControl to update controls when adding/deleting tabs. Specifically:

Selecting a new tab with || now works correctly.
Deleting all tabs now hides the controls of the former tab.

Fixed +Disabled/+Hidden losing effect on controls in a tab.
Fixed disabled tab controls to ignore Ctrl+Tab.


Fixed Gui Tab without parameters to start a new radio group if applicable. Gui Tab with parameters already had this effect.
1.1.23.07 - May 20, 2016

Fixed Menu x, Insert, y, z, % object to use the object, not ignore it.

Fixed Menu x, Add, :item text, % object to use the object, not look for a submenu.
1.1.23.06 - May 15, 2016

Fixed break label crashing the program if nested directly inside its target loop.
1.1.23.05 - March 27, 2016

Fixed InputBox, MsgBox, FileSelectFile and FileSelectFolder sending an unwanted Alt-up if Alt is down. This was due to an error with the Ctrl/Shift workaround added in v1.1.22.01.

Improved the Ctrl/Shift workaround to avoid unnecessarily "masking" the Win key if Ctrl, Shift or Alt is also down.
1.1.23.04 - March 26, 2016

Fixed LV_Modify to support omitting Options, as in LV_Modify(r,, col1).
1.1.23.03 - March 12, 2016

Fixed __Delete meta-functions erroneously suppressing or prematurely re-throwing exceptions, when they are called during exception propagation.

Fixed load-time detection of function calls where a required parameter is blank, as in fn(x,,y).
1.1.23.02 - March 12, 2016

Fixed RegDelete deleting the entire key instead of the default value.
Code maintenance; minor code size improvement.

1.1.23.01 - January 24, 2016

Fixed a theoretical issue with loading scripts from weird/very long paths.
Ahk2Exe: Fixed Unicode in compiled scripts (broken by v1.1.23.00 release).
1.1.23.00 - January 16, 2016

Added Menu Insert sub-command.

Added MenuGetHandle().

Added MenuGetName().

Added menu item options: Radio, Right, Break and BarBreak.

Improved the Menu command to allow identifying items by position: 1&

Added LoadPicture().

Added hicon/hbitmap: syntax for passing handles to commands which normally load an image from file.

Added built-in variables: A_CoordModeToolTip/Pixel/Mouse/Caret/Menu, A_DefaultGui, A_DefaultListView, A_DefaultTreeView, A_KeyDelayPlay, A_KeyDuration/Play, A_MouseDelayPlay, A_SendLevel, A_SendMode and A_StoreCapsLockMode.

Added Ix Hotkey option to set the hotkey variant's input level to x.
Improved Picture control to support BackgroundTrans with icons.
Improved Picture control to reduce flicker when loading large images.


Small optimizations to the menu code and built-in var lookups.

Fixed conversion of menu items to/from separators.

Fixed A_ThisMenuItemPos to support duplicate item names.

Fixed sub-menus sometimes not being recreated after a menu is deleted.

Fixed AutoHotkeyXXX.exe to launch AutoHotkey.chm, not AutoHotkeyXXX.chm.
1.1.22.09 - November 11, 2015

Fixed some issues with SetTimer Delete.

KeyHistory's timer count erroneously included deleted timers.

Calling KeyHistory within a thread started by a timer crashed the script if the timer had been deleted but not turned off.
Deleting the most recently created timer prevented subsequently created timers from working unless ALL timers were deleted.

1.1.22.08 - November 11, 2015

Fixed For-loop to pass control correctly when _NewEnum/Next throws an exception.

Fixed Finally to suspend the pending exception until its body has been evaluated, not just until the first built-in function call.
Fixed load-time detection of invalid jumps from Finally blocks (broken by v1.1.20).

1.1.22.07 - September 27, 2015

Fixed Gui control w-1 and h-1 options failing when DPI is 150+% and the Gui has not applied -DPIScale.

Fixed ~key up hotkeys to not perform an automatic Send {key down}. This was occurring only if the hotkey was turned on after the key was pressed down.

1.1.22.06 - September 13, 2015

Fixed Input and hotstrings to catch Unicode/non-key character events.

Fixed auto-sizing of Edit controls to include the last line if blank.

Fixed handling of out-of-memory in ComObj functions.

Fixed ComObjArray to ignore excess parameters rather than crashing (only applies to dynamic calls).
Fixed GuiControl to append--not prepend--tabs, as documented.

Fixed XP64 support.

1.1.22.05 - September 10, 2015

Fixed icons which have non-numeric IDs loading with sub-optimal quality.

Fixed Gui Destroy not releasing function objects which were set by the +g option.
Fixed Gui Show to avoid attempting to force-activate a child GUI.

Fixed failure to set Caps/Num/ScrollLock state while the key is down.

Fixed Gui Color causing incorrect text color (usually black).

Changed Gui Show to improve the odds of GuiSize executing immediately.

For developers:

Modified project config to support more VC++ versions.

Fixed various build warnings on VC++ 2015.

64-bit binaries are now built with VC++ 2015. 32-bit binaries still use VC++ 2010.

1.1.22.04 - August 19, 2015


Fixed ObjRawSet() to return nothing.

Added Windows 10 supportedOS tag to the exe manifest (avoids some issues with the Program Compatibility Assistant and similar).
Added detection of syntax errors after ")" in a function declaration.

1.1.22.03 - July 12, 2015

Fixed A_EndChar returning a truncated value for Unicode end chars.
Small implementation changes:

Changed A_Language to use GetSystemDefaultUILanguage().

Refactored Window Spy/help file launching from tray menu to improve code re-use.
Optimized Gui/Menu/Hotkey/Hotstring/OnClipboard message handling (minor).

1.1.22.02 - May 27, 2015

Fixed TreeView to not raise * events for unknown notifications.

Fixed crashing/bad behaviour when a timer deletes itself.

Fixed RWin-up being masked in some rare cases where LWin-up wouldn't have been.
1.1.22.01 - May 24, 2015

Fixed Text/Edit/Button control sizing to compensate for character overhang.

Fixed registry commands to allow : in the SubKey when combined with RootKey.

Fixed hotkey prioritization to take modifiers into consideration.

Refactored else/try/catch/finally handling to support hotkey::try cmd.

Added a workaround for the script's dialogs acting as though Ctrl or Shift is pressed after they are blocked by the keyboard hook.
1.1.22.00 - May 1, 2015

Added SetErrorMode(SEM_FAILCRITICALERRORS) on program startup to suppress system-level error messages such as "There is no disk in the drive". Calling Drive or DriveGet no longer affects the process' error mode.

Changed MonthCal controls to have tab-stop by default on Vista or later.

Improved ComObjConnect to use IProvideClassInfo when available.

Fixed some issues with method/property definitions following an end brace on the same line.
Fixed Text/Link control auto-sizing to compensate for the +Border (WS_BORDER) style.
Fixed Break N when Loop is used directly below If/Else/Try/Catch.

1.1.21.03 - April 12, 2015

Fixed detection of naming conflicts between properties and methods.
1.1.21.02 - April 4, 2015

Fixed OnMessage(msg, fnobj, 0) to do nothing if fnobj wasn't previously registered.
1.1.21.01 - April 3, 2015

Fixed StrReplace() to allow ReplaceText to be omitted.
Fixed class variables to allow non-ASCII names.
1.1.21.00 - March 28, 2015


Added Loop, Reg, RootKey[\Key, Mode].

Added Loop, Files, FilePattern [, Mode].

Changed InputVar parameters to allow % expression (except with If commands).
Revised Object methods:

Added Object.InsertAt(), Object.Push() and ObjRawSet().
Added Object.Delete(), Object.RemoveAt() and Object.Pop().
Added Object.Length().

Added Ord() and updated Chr() to support supplementary chars (>0xFFFF).

Added StrReplace().

Removed the obsolete and undocumented 5-parameter mode of RegRead, which was exclusively for AutoIt v2 compatibility (the extra
parameter was unused).

Changed RegRead, RegWrite and RegDelete so that the RootKey and SubKey parameters can optionally be combined.
1.1.20.03 - March 21, 2015

Fixed MouseGetPos (OutputVarControl), GuiContextMenu and GuiDropFiles (A_GuiControl) to not ignore disabled controls [broken by v1.1.20.00].

1.1.20.02 - March 11, 2015

Fixed add-first mode of OnMessage.

Fixed A_OSVersion for unrecognized OSes on x64 builds.

Fixed ExitApp to unpause the script before releasing objects in case a __delete meta-function is called.
Trivial optimizations and code maintenance.

1.1.20.01 - March 10, 2015

Reverted the changes made in v1.1.20.00 to saving and restoring of ErrorLevel on thread interrupt, due to unintended consequences.
ErrorLevel is not reset or cleared when a new thread starts. Instead, it retains the value it had in the interrupted thread, as in

v1.1.19 and older.

If ErrorLevel contains an object and the thread is interrupted, the object is replaced with an empty string when the thread resumes,
as in v1.1.19 and older.

If ErrorLevel contains a string longer than 127 characters, it is truncated when the thread resumes, as in v1.1.19 and older.

Re-fixed timers sometimes causing ErrorLevel to be formatted as hex.
Fixed class methods to retain a counted reference to the class.
1.1.20.00 - March 8, 2015

New features:

Enhanced Hotkey, Menu, SetTimer, Gui events and Gui control events to accept a function instead of a label, if no label is found.
Enhanced Hotkey, Menu, SetTimer and Gui control events to accept a function object. Added a Delete sub-command for SetTimer to
allow the object to be released.

Enhanced OnMessage() to allow any number of functions or function objects to monitor a single message.
Added OnExit() and OnClipboardChange(), which accept a function name or object.

Added capability to point hotkey labels at a function definition.

Added U/L/T modifiers to perform case conversion with Format().

Added the E option to the Input command, for handling end keys by character instead of keycode.

Added ** (stderr) support to FileAppend.


Added ObjBindMethod(obj, method, args*) and Func.Bind(args*).
Changes:

Changed the default behavior when the main script file is not found:

If no script was specified and the default script files are not found, show the new Welcome page in the help file.

If a script was specified or the help file is missing (or is named differently to the executable), just show an error message.

Changed WinActivate to restore the window if already active but minimized.

Changed WinActivate to look for a visible window to activate if DetectHiddenWindows is off and the active window is hidden, instead of doing nothing.

Changed the method used by A_CaretX/A_CaretY to retrieve the caret position.

Returns blank in more cases where the real caret position can't be determined, instead of returning the top-left of the active

window.

Less likely to cause side-effects.
Works in console windows.

Changed A_OSVersion to use RtlGetVersion(), so that it can detect Windows 10 and hopefully future versions.
Changed A_OSVersion to return a version number of the form "major.minor.build" if it doesn't have a name for the OS.
Changed objects to support x[,y], x.y[,z] and x[](y).

User-defined objects can utilize this by specifying default values for parameters of properties and meta-functions. For __Call, the
first parameter is omitted, as in x.__Call(,y).

COM objects invoke DISPID_VALUE if the member name is omitted. For example, x[] retrieves x's default property and fn[]()
can be used to call JScript functions.

Several under-the-hood changes to fix bugs, reduce code size or improve performance, including:
Changes to preparsing of #if and static var initializers.

Changes to preparsing of { blocks }.

Bug-fixes:

Fixed VK to keyname conversions for keys 'A' to 'Z' to respect layout.

Applies to: GetKeyName, Hotkey control, A_PriorKey, KeyHistory and Input EndKey ErrorLevel (except where Shift key is
required).

All other keys, including those that produce non-ASCII letters, were already translated according to AutoHotkey's current
keyboard layout.

Fixed FileAppend to * (stdout) to respect the encoding parameter instead of always outputting ANSI text.

Fixed auto-sizing of GUIs with only one scrollbar.

Fixed Exception(m, n) crashing when n is too far out of bounds.

Fixed GuiContextMenu to set A_GuiEvent correctly on x64.

Fixed FileGetSize sometimes giving an indeterminate result if the file doesn't exist or can't be opened.

Fixed thread interrupts to save and restore ErrorLevel more fully [reverted in v1.1.20.01 due to unintended consequences].
Fixed ControlClick Pos mode to ignore disabled controls.

Fixed odd behaviour when Gui +MaxSize is smaller than +MinSize.

Fixed GuiControl/Get requiring a Gui name when given a control HWND.

Fixed meta-functions interfering with the line number reported by Exception().

1.1.19.03 - February 11, 2015

Improved remapping to allow scXXX::Y when the current keyboard layout does not map scXXX to a VK code. However, Y must still exist on the current keyboard layout.

Fixed break n to work correctly when until is present, instead of terminating the thread.


Fixed ControlGetFocus disrupting the user's ability to double-click (thanks HotKeyIt).

Fixed ListView to not call the control's g-label for unsupported (and previously unknown) notifications such as
LVN_GETEMPTYMARKUP.

Fixed #Include *i <X> to exit the program as intended if X has a syntax error.

Fixed for var in expression sometimes crashing the program when expression calls a script function.
1.1.19.02 - January 25, 2015

Removed the 16-color icons which were used on Win9x/Win2k.
Removed the separate tray icon resources.

Improved selection of icon size when loading icons from DLL/EXE files.

In short, prefer to downscale rather than upscale. This is especially helpful on systems with 125% or 150% DPI, where the system
icon sizes are 20/40 or 24/48 instead of 16/32. If all of these sizes are present in the icon resource, this change makes no difference.

Fixed some issues with hotkey validation at load time.

Hotkeys which are never valid, like foo::, are now always treated as errors instead of giving a misleading warning about keyboard

layout.

Hotkeys like ^!ä:: which are inactive because of the current keyboard layout are now allowed to have a same-line action, and the
label is registered correctly (e.g. as "^!ä" and not as "^!ä:"). If the /iLib command line switch is used, the warning is suppressed.
Remappings which are inactive because of the current keyboard layout now show two warnings instead of an unrecoverable error.
If a Wheel hotkey is used as a prefix key, there is only one error message instead of two, and it respects /ErrorStdOut.

Fixed /iLib switch to write the file even if there's a syntax error.
Fixed return/break/continue/goto in try..finally.

1.1.19.01 - January 5, 2015

Fixed Hotkey command crashing the program when trying to create new variants of existing hotkeys (broken by v1.1.19.00).
Made some minor optimizations to the Hotkey command and A_TimeIdle, relating to removal of Win9x support.
1.1.19.00 - January 4, 2015

Added a name for Func.Call(). Func.() still works but is deprecated.
Fixed some issues with X.Y and X.Y(Z) in VBScript/JScript/C#:

If X.__Call contained a function name, it was being returned instead of called.

When X.Y(Z) returned a value, Z was ignored. Now it acts like X.Y[Z] when X.Y is not a function.

Fixed the Hotkey command ignoring the ~ (pass-through) prefix if Label was omitted.

Fixed the Hotkey command ignoring the $ (use-hook) prefix if the hotkey variant was already created without $.
Fixed %Fn%() syntax to work with JavaScript Function objects.

Fixed EXE manifest to disable UAC installer detection heuristics (broken by v1.1.17).

Improved the way threads are represented on the debugger's call stack.

The type of thread is shown instead of the label name, which is still available in the next stack entry. For hotkeys, the hotkey is
shown instead.

The line number of the sub or function that the thread called is shown instead of the line the script was at before starting the
thread.

1.1.18.00 - December 30, 2014

Improved IDispatch implementation for AutoHotkey objects:

X.Y in VBScript and C# now returns X.Y if it is NOT a Func object; previously, it attempted to call X.Y() regardless of type.

X(Y) in VBScript, JScript and C# now returns X[Y] unless X is a Func object, in which case it is called as before.
X[Y] in C# now returns X[Y] if X is NOT a Func object; previously, it attempted to call X[Y]() regardless of type.


X.Y() in C# now returns X.Y if it is NOT a Func object, due to ambiguity in the C# dispatch implementation.
Unhandled exceptions are now converted to IDispatch exceptions.

Added support for creating new properties in JavaScript/IE DOM objects.
Fixed FileAppend, %VarContainingClipboardAll%, File causing crashes.
1.1.17.01 - December 28, 2014

Fixed COM event handlers not receiving the final object parameter.
1.1.17.00 - December 27, 2014

New features:

Added Format().

FileOpen() can now be used to read from stdin or write to stdout or stderr by passing "*" or "**" as the filename. AutoHotkey.exe * can be used to execute script text piped from another process instead of read from file. For an example, see ExecScript().

Added support for passing AutoHotkey objects to COM APIs as IDispatch.

Added support for VT_BYREF in ComObject wrappers. Use obj[] to access the referenced value.

Bug-fixes:

Fixed blue-screening on XP SP2.

Fixed owned ComObjArrays to be returned by value, not by pointer. That is, a copy of the array is returned instead of a pointer to an
array which is about to be deleted.

Changed the URL in the sample script which is created when you first run AutoHotkey.
Fixed sc15D to map to vk5D/AppsKey (Send, GetKeyName, etc.).

Fixed Edit controls to not treat AltGr+A as Ctrl+A.

Fixed static class vars to not act as a target for labels which immediately precede the class.
1.1.16.05 - September 28, 2014

Fixed x.y/[]/{} sometimes falsely being flagged as variadic.
1.1.16.04 - September 16, 2014

Fixed a crash which occurred when overwriting a non-writable property.

Fixed a crash which occurred when a RegExMatch object is created with uncaptured subpatterns during a regex callout.
1.1.16.03 - September 11, 2014

Fixed some bad behaviour in Abs() and Mod() caused by a broken bug-fix in v1.1.16.01.
1.1.16.02 - September 11, 2014

Fixed parser to allow #include inside a class (broken by a6ea27f).
Fixed Clipboard returning binary CF_HDROP data in some instances.
Improved accuracy of FileGetSize on files which are still open.
Improved for-loop compatibility with COM objects.

1.1.16.01 - September 10, 2014

Added syntax for defining dynamic properties in classes.
Added x+m and y+m options for Gui control positioning.


Added the #InputLevel of each hotkey to ListHotkeys (when non-zero).

Optimized RegExMatch with the O (object) option; capturing part of a long string is much faster than before in some cases.
Fixed objects to check for new methods after __Call completes (consistent with __Set and __Get).

Fixed some undefined behaviour occurring after VarSetCapacity fails.

Fixed FileRead to correctly report an error with files over 4GB, instead of truncating even when it wasn't requested.

Fixed FileRead *c to null-terminate correctly when byte length is odd.

Fixed some ClipboardAll issues and changed behaviour:

#ClipboardTimeout is ignored for GetClipboardData(), since it never actually worked and it caused problems. This fixes timeouts
and lost data when a file is on the clipboard (any file on Windows 8, or any file in a zip file or similar).

Zero-length clipboard items are allocated 1 byte upon restoring to the clipboard, since setting a zero-length item seems to always
fail.

The presence of MSDEVColumnSelect/MSDEVLineSelect is now preserved when set by Scintilla, though any data set by VS is
discarded.

When writing ClipboardAll directly to file, it now prefers Unicode (other usages of ClipboardAll have had this behaviour since
v1.1.08).

ClipboardAll and FileRead *c on Unicode builds now round length up when odd. This increases the reported StrLen by 1,
potentially avoiding truncation of the last byte.

Fixed A_EventInfo for TreeView items with negative screen coords.
Fixed a possible ListView/TreeView message filtering issue.

Fixed A_LineFile/A_LineNumber in #If expressions.

Fixed #If to add itself to ListLines (though as "If").

Fixed Abs(["-"]*) and similar crashing the program.

Fixed } funcdef(){ globally and }} ending a method/property/class.
1.1.15.04 - August 12, 2014

Fixed a performance issue with &var_containing_long_string_of_digits.

Fixed built-in variables corrupting memory when an object is assigned.

Fixed parser to disallow continue where appropriate even if the current function is defined inside a Loop.

Fixed File.Encoding := x "-RAW" breaking encoding/decoding of non-ASCII characters. The -RAW suffix is now ignored.
1.1.15.03 - August 2, 2014

Fixed meta-functions to exit the thread correctly after using Exit or Throw.

Fixed FileInstall to use A_WorkingDir when Dest is relative in a non-compiled script.
1.1.15.02 - July 7, 2014

Fixed debugging negative integer keys in objects.
1.1.15.01 - June 30, 2014

Changed built-in error and warning dialogs to be always-on-top.
Fixed Until not breaking out of recursive file/registry loops.
1.1.15.00 - May 4, 2014

Added A_OSVersion value WIN_8.1.

Changed the Hotkey command to apply/remove passthrough behavior on existing hotkey variants depending on whether the tilde (~)
prefix is present.


Changed exe manifest to allow GetVersion/GetVersionEx to detect Windows 8.1.
1.1.14.04 - April 25, 2014

Fixed DllCall() crashing the script when Function is pure integer 0.

Fixed IsFunc("ComObj(") to return false instead of throwing an exception.
Fixed ControlClick to send XButton1/XButton2 correctly.

1.1.14.03 - February 14, 2014

Fixed a memory leak in new X when X.__Init aborts the thread.

Fixed breakpoints shifting onto class var initializers when they are interspersed with method definitions.
1.1.14.02 - January 30, 2014

Fixed x:: and x up:: both firing on key-up if the state of the modifier keys prevented x from firing on key-down. The intended
behaviour as of v1.1.14 is for both hotkeys to fire on key-up if x is also used in a custom combination like x & y::.

1.1.14.01 - January 15, 2014

Fixed Try without Catch/Finally crashing if no exception was thrown.
1.1.14.00 - January 15, 2014

Added Finally statement for performing cleanup after try/catch. [fincs]
Changed behaviour of ~ prefix with custom combos to be more intuitive.
Fixed x & y:: to fire both x:: and x up:: when x is released.

Fixed ImageSearch to set ErrorLevel=2, not 0, when a GDI call fails.
Fixed EnvGet crashing the program when the var exceeds 32767 chars.
Fixed a minor error-handling bug with StatusBarWait's ErrorLevel.

Fixed a cause of heap corruption with FileRead *c on ANSI builds.

Fixed passing of local vars in recursive calls to variadic functions.

Fixed script failing to load if the first line is an expression in parentheses.
Fixed PixelSearch Fast mode to set OutputVarX/Y only on success.
1.1.13.01 - October 11, 2013

Fixed variadic function calls with named values for required parameters.
1.1.13.00 - August 27, 2013

Ported StrSplit() from v2 alpha.
1.1.12.00 - August 14, 2013

Optional parameters can be omitted by writing two consecutive commas, as in InStr(a, b,, 2). Unlike previous versions, this now works for objects (including COM objects) and built-in functions. [a,,b] can be used to create a sparse array.

Object properties can now be set using variadic syntax, as in x[y*]:=z, where y contains an array of keys/indices or parameters.
1.1.11.02 - July 28, 2013

Fixed GuiControl/Get to accept the ClassNN of a ComboBox's child Edit. Specifying the HWND of a ComboBox's child Edit was
already supported as a means of identifying the ComboBox.


1.1.11.01 - June 25, 2013

Fixed InputBox default width/height (broken by v1.1.11.00 - commit 7373cc6443).

Fixed DllCall arg type validation to handle SYM_OBJECT safely, and to respect #Warn UseUnset (when var name is not a valid type). Changed VarSetCapacity(var) to never warn about uninitialized vars.

1.1.11.00 - June 21, 2013

Added support for %A_LineFile% in #Include.

Reduced the file size of AutoHotkeySC.bin by reducing the resolution of the (rarely used) filetype icon.

Fixed class X extends Y to allow Y to be defined after X.

Developed by fincs: AutoHotkey is now DPI-aware. The Gui commands automatically compensate when DPI is not 96. See Gui -
DPIScale.

1.1.10.01 - May 17, 2013

Improved RegRead to support REG_BINARY values larger than 64K.

Improved RegWrite to support REG_BINARY/REG_MULTI_SZ values larger than 64K.
Fixed Process Close (and possibly other things) on Windows XP.

1.1.10.00 - May 11, 2013

Added basic support for custom Gui control types.

Revised SoundSet, SoundGet and 'WaveVolume commands to better support Windows Vista and later.
Fixed Run "<file>" <args> to not pass the space as part of the args.

Fixed some issues with reading from console input (CONIN$).

1.1.09.04 - March 14, 2013

Fixed Gui menu accelerator keys not working when the Gui itself (not a control) has focus.
1.1.09.03 - February 9, 2013

Fixed two bugs which affected certain assignments where the target variable contains an unflushed binary number but has zero capacity. Fixed GuiControl and GuiControlGet acting on the wrong control when given a HWND which does not belong to the current Gui.
Instead, the condition is treated as an error.

Fixed OnMessage functions to set A_Gui and A_GuiControl correctly when the target Gui is a child window.
1.1.09.02 - December 24, 2012

Fixed MsgBox to show an error message when given invalid Options, instead of silently exiting the thread.
Fixed syntax errors in class var initializers causing the program to crash without the proper error message.
1.1.09.01 - December 15, 2012

Fixed AND/OR following a multi-statement comma, like ((x, y) and z).
Fixed RegExReplace to support duplicate subpattern names correctly.
Fixed Object.Remove() not freeing string keys.

Fixed base.Invoke() to not depend on dynamic variable resolution.
1.1.09.00 - November 7, 2012


Breaking changes:

Removed .aut file compatibility and #AllowSameLineComments.

Removed undocumented AutoIt v2 commands.

Backward-compatible changes:

Allow optional parameters to be declared with := instead of =, for consistency with variable declarations and expressions.

Allow non-ASCII characters in unquoted keys ({key: x} and obj.key).

Changed name in version info from "AutoHotkey_L" to "AutoHotkey".

Bug-fixes:

Fixed instability caused by warning dialogs appearing part-way through evaluation of a command's args.

Fixed PixelSearch Fast mode treating "not found" as an error.

Fixed ahk_exe to allow other ahk_ criteria after it.

Fixed else continue 2 and similar requiring braces around the loop.

Fixed RegRead indicating failure after successfully reading binary data.

Fixed File.Length to compensate for or flush any buffered data.

Fixed Gui sizing to account for scrollbars when present.

Debugger:

Added support for asynchronous commands.

Improved handling of breakpoints on lines like else foo() or { bar() so that the debugger will actually break when appropriate.
Optimized code size, fixed several bugs and made the debugger generally more robust.

1.1.08.01 - August 3, 2012

Debugger: Fixed max_depth being either half the intended limit or unlimited.
1.1.08.00 - July 14, 2012

Breaking changes:

Changed the default script codepage to ANSI, as the previous behaviour was a common source of confusion. UTF-8 files must now have a byte order mark (BOM) to be recognized correctly. Notepad adds a BOM to any file saved as UTF-8.

Changed return x to preserve formatting of numeric strings; it is now equivalent to return (x).

Changed Gui, Name: New to set the new GUI as the default.

Other changes:

Changed ClipboardAll to prefer CF_UNICODETEXT over other text formats.

Changed Gui Show to allow floating-point numbers.

Changed A_OSVersion to return WIN_8 on Windows 8.

Changed AutoHotkey.exe file description to include "ANSI/Unicode 32/64-bit".

Changed the parser to allow lines like new MyObject() with no assignment.

Upgraded PCRE to 8.30.

Improved wording of some warnings and added a pointer to the documentation at the bottom of the warning dialog.
Improvements to the debugger:

Added basic support for inspecting Func, ComObject and RegExMatchObject objects.


Fixed the "attach debugger" message being ignored in some situations. See commit 83f0a0e.

New features:

Added support for the PCRE construct (*MARK:NAME) via RegExMatchObject.Mark.

Added support for classvar.x := y assignments in class definitions (after declaring classvar).

Added A_Is64bitOS.

Added SetRegView and A_RegView.

Fixes:

Fixed Func.() to merely skip the function call if mandatory parameters were omitted instead of causing the thread to silently exit.
Fixed Object.Remove() not releasing object keys.

Fixed key-down/key-up hotkey pairs to suppress input correctly when only one hotkey in the pair is enabled.

Fixed #Include <Lib> to not affect the working directory used by subsequent #include directives.

Fixed objaddref() acting like ObjRelease() when called with a lower-case 'a'.

Fixed A_AhkPath in 32-bit compiled scripts to detect 64-bit AutoHotkey installations and vice versa.

Fixed TreeView controls with -Background option rendering incorrectly on older OSes.

Fixed error messages shown during execution of While/Until to identify the appropriate line.

1.1.07.03 - March 25, 2012

Fixed Ctrl/Alt/Shift key-down hotkey breaking any corresponding key-up hotkey defined before it.

Fixed key-down hotkeys to always use the hook if defined after a key-up hotkey of the same key. If the key-down hotkey used the "reg" method, the hook would block the key-down event and trigger only the key-up hotkey.

Fixed load-time checks interpreting expressions with no derefs as raw text. For example, gosub % "foo" resolved to "foo": at load-
time. Similarly, % "" was seen as invalid in various cases even if an empty string should be allowed.

1.1.07.02 - March 22, 2012

Fixed a rare crash which can occur when GetClipboardData() fails.

Fixed ComObjArray() to return an empty string on failure instead of an arbitrary integer.
Fixed Object.Remove(i, "") affecting integer keys when !Object.HasKey(i).
1.1.07.01 - March 2, 2012

Fixed FileRead to ignore #MaxMem when reading UTF-16 on Unicode builds.
Fixed dynamic function calls with built-in vars such as %A_ThisLabel%().
1.1.07.00 - February 27, 2012

Enhanced %var%() to support function objects and the default __Call meta-function.

Fixed ControlGet List to work for ListViews where the script and the target process aren't both 32-bit or both 64-bit.

Fixed SendEvent with a key delay of 0; a change introduced by v1.1.05.04 caused it to be slower than intended.

Fixed Object.Remove(i) not adjusting keys if Object[i] doesn't exist.

Fixed an error in ComObjType() which may have caused unpredictable behaviour when it is called via an alternative name.

Fixed ExitApp to exit the thread if an OnExit subroutine prevents the script from terminating, instead of resuming execution after the
block which contained ExitApp.

Calling a function via an object no longer acts as a barrier to exiting the thread. Consequently, if Exit is used or a runtime error occurs


within a class method, the entire thread exits instead of just the function.

Calling a base-class method using base.Method() or similar inside a class definition no longer causes a UseUnset warning if the method doesn't exist. Consequently, instantiating an object which has instance variables no longer causes a warning about the internal
base.__Init method if the base class has no instance variables.

1.1.06.02 - February 13, 2012

Fixed IniRead crashing when Section is omitted but Key isn't.
Fixed accuracy of FileGetSize with files which are 4GB or larger.
1.1.06.01 - February 12, 2012

Fixed MsgBox smart comma handling to require numeric Options, not Title.
1.1.06.00 - February 12, 2012

New features:

Integrated #InputLevel directive and SendLevel command by Russell Davis.

Integrated support for Link controls by ChrisS85.

Breaking changes:

Changed command parser to avoid trimming escaped characters such as `t or `  at the beginning or end of an arg.
Changed MsgBox's smart comma handling to improve flexibility and consistency.

% can now be used to make Options or Timeout an expression.

If the first arg is an expression, any unescaped comma which is not enclosed in quote marks or parentheses/brackets/braces will
cause multi-arg mode to be used. These commas were formerly interpreted as multi-statement operators within the first-and-only
arg (Text).

When Title is an expression, unescaped commas contained within the expression no longer interfere with smart comma handling.
If there are exactly two args and the first is empty or an integer, multi-arg mode is used. The former behaviour was to combine
both into a single arg (Text).

Timeout can be a literal number or a single deref (and optionally part of a number; for example, %Timeout%.500). Contrary to the
documentation, the former behaviour interpreted most other cases beginning with % as expressions (containing a double-deref).
Title can be an expression even if Text and Options are omitted.

Changed A_IsUnicode/A_IsCompiled to be defined as an empty string in ANSI versions/uncompiled scripts instead of being left
undefined. This allows them to be checked without triggering #Warn warnings. Side effects include:

Attempting to assign directly to A_IsCompiled or A_IsUnicode always causes a load-time error. Dynamic assignments always fail,
either silently or with an error dialog as appropriate. Previously assignments were allowed in uncompiled/non-Unicode scripts.
Attempting to take the address of A_IsCompiled or A_IsUnicode always fails.

A_IsCompiled and A_IsUnicode no longer appear in ListVars when referenced by a script which is not compiled/Unicode.

Changed Send and related commands to respect #MenuMaskKey when changing modifier keystates.
Other changes:

Changed GuiControl Choose to remove the ListBox/ComboBox/DDL's current selection when N=0.
Changed RegisterCallback to allow a Func object in place of a name.

Changed ListLines to show filenames (except when compiled).

Improved Run to output a process ID if possible when ShellExecuteEx is used.

Fixes:

Fixed handle leaks in RegRead.

Fixed x.y++ and similar to assign an empty string if x.y is non-numeric.

Fixed SendInput Win+L workaround causing Win key to "stick down".

Fixed Ahk2Exe auto-including the wrong file if an auto-include used #Include <Lib>.


1.1.05.06 - December 31, 2011

Fixed inc (++) and dec (--) having no effect when used on an object field containing a string.
Fixed inc (++) and dec (--) to cause a warning when used on an uninitialized variable.
1.1.05.05 - December 17, 2011

Fixed continue n misbehaving when an inner loop has no braces.

Fixed RegExMatchObject[Name] to work correctly with duplicate names.
1.1.05.04 - December 5, 2011

Fixed: Selected sub-command of ControlGet was unreliable on x64.

Fixed: CPU was maxed out while waiting if an underlying thread displayed a dialog (and possibly in other cases).
1.1.05.03 - November 30, 2011

Fixed Loop ... Until VarContainingObject.
1.1.05.02 - November 20, 2011

Fixed false detection of end-of-file when loading a compiled script in some cases.

Fixed SendInput to automatically release modifier keys when sending special characters or {U+xxxx} (which was broken by v1.1.00.01). Fixed ComObjConnect to filter out non-dispatch interfaces instead of allowing the script to crash.

Fixed new %VarContainingClassName%().

1.1.05.01 - October 16, 2011

Fixed class declarations to allow directives such as #Include.
1.1.05.00 - October 8, 2011

Added Client coordinate mode.

Added object output mode for RegExMatch and RegEx callouts.

Added super-global declarations, which avoid the need to repeat global declarations.

Breaking change: Class declarations such as Class c now create a super-global variable instead of an ordinary global.
Added more detail to unhandled exception error dialogs.

Changed Gui +Owner to work even after the GUI is created.

Changed instance var declarations in class definitions to avoid leaving empty key-value pairs in the class object.
Changed #Include to use standard error message formatting when it fails (more detail; also respects ErrorStdOut).
Changed Throw to throw an Exception object by default when its parameter is omitted.

Changed format of runtime error messages slightly to improve consistency and code size.

Modified PCRE to use UTF-16 for input on Unicode builds, for performance.

Upgraded PCRE to 8.13.

Fixed thread not exiting as intended when an assignment in an expression fails.

Fixed #MaxMem preventing assignments to variables which don't require expansion.

Fixed inability of Try/Catch to catch COM errors.


Fixed GuiControlGet incorrectly treating parameter #2 as invalid in some cases.

Fixed input vars being resolved too soon, allowing them to be invalidated by an expression later on the same line.
Fixed RegEx callouts not causing matching to abort when an exception is thrown.

Fixed DllCall setting ErrorLevel to -4 when it should be -3.

Fixed While appearing twice in ListLines for its first iteration.

Fixed Try/Catch to allow If/Loop/For/While with no enclosing block.

Fixed enumerator object not being released when Until is used to break a For-loop.

1.1.04.01 - September 15, 2011

Fixed FileRemoveDir setting ErrorLevel incorrectly.
1.1.04.00 - September 11, 2011

Warning: This release contains a number of potentially script-breaking changes.

Added exception handling support: try/catch/throw and Exception().

Added StdOut mode for #Warn.

Added Gui +HwndVARNAME option.

Added Gui, New [, Options, Title].

Added automatic support for keyboard accelerators such as Ctrl+O in Gui menus.

Changed handling of #Include <Lib> when the /iLib command-line switch is present to resolve a problem with Ahk2Exe.
Changed GuiControl to retain the Progress control's current value when its style is changed.

Changed GuiControl and GuiControlGet to allow a HWND to be passed in the ControlID parameter.

Removed the 1GB limit from FileRead.

Improved error detection:

Hotkey, If, Expression, where Expression does not match an existing #If expression, is caught at load-time when possible.
Hotkey, IfSomething, where Something is invalid, is caught at load-time.

Class definitions with missing braces are detected as errors.

If a function call is used on the first line of a class definition, it is now correctly treated as an error.

GroupAdd now shows an error message when the group name is blank, instead of silently exiting the thread.

Removed some redundant "unset var" warnings which appeared when using the OutputDebug or StdOut warning modes.

If an unrecognized option is used with Gui, Gui Show, Gui New or GuiControl, an error message is shown and the thread exits
unless try is used. This validation is not done at load-time due to complexity (it is common for the option parameters to contain
variable references).

RegRead, RegWrite and RegDelete now set A_LastError to the result of the operating system's GetLastError() function.
+LastFoundExist is now treated as an error if it is combined with another option (+LastFound should be used in that case).

Fixed a bug affecting recursive variadic functions.
1.1.03.00 - August 28, 2011

Added support for GUI names.

Added support for identifying a GUI by its HWND.

Added +Parent%ParentGui% Gui option.

Added support for external windows as Gui owners via +Owner%HWND%.
Added Name sub-command for GuiControlGet.

Added support for ActiveX controls via the Gui command.

Fixed: Empty hotkey control returned "vk00".


Fixed: Crashes and memory leaks related to COM events/ComObjConnect.
Fixed: GuiControlGet OutputVar, Subcmd, %OutputVar% always failed.
Changed "Missing (/[/{" error messages to "Unexpected )/]/}" for greater clarity.

Changed ListLines to display While and Until lines which are executed each iteration.

Changed ~= to have higher precedence than =/!=/</>/<=/>= but lower than concat, and added it to the documentation.
1.1.02.03 - August 21, 2011

Fixed (Debugger): numchildren attribute did not include Object.Base.
1.1.02.02 - August 20, 2011

Fixed: Variable capacity was capped at 2GB on x64 builds.
Fixed: Last Found Window not set by #if WinExist(T).
1.1.02.01 - August 13, 2011

Changed A_PriorKey to exclude key-up events.

Fixed process name/path retrieval in certain cases, including:

Retrieving name/path of a 64-bit process from a 32-bit script.

Retrieving name/path of an elevated process from a non-elevated process (UAC).

1.1.02.00 - August 6, 2011

Added TV_SetImageList().

Characters which require non-standard shift states 16 and 32 now use a fallback method instead of producing the wrong keystrokes. Revised handling of dead keys to solve problems which occur when multiple scripts with hotstrings are active.

1.1.01.00 - July 30, 2011

Added support for instance variables in class definitions, using simple assignment syntax.

Removed var keyword used in class definitions; use static instead.

Added new built-in variables: A_ScriptHwnd and A_PriorKey.

Added new built-in functions: GetKeyName(), GetKeyVK(), GetKeySC() and IsByRef().

Added new sub-command: WinGet, OutputVar, ProcessPath.

Added the capability to specify a window by process name or path: ahk_exe %Name%.exe or ahk_exe %FullPath%.
Optimized ProcessName sub-command of WinGet.

Changed SetTimer to use A_ThisLabel if Label is omitted.

Updated ComObjConnect() to support using an object in place of a function name prefix.

Improved ComObjConnect() to allow the prefix/object to be updated without first disconnecting.

Improved parsing of continuation sections to allow expressions like (x.y)[z]() without escaping "(".

Replaced the method used to store script text in 32-bit compiled scripts; now consistent with 64-bit.

Fixed detection of AltGr in the active window's keyboard layout (on Unicode builds).

Fixed SendInput applying a redundant LCtrl-up some time after AltGr-up.

1.1.00.01 - July 17, 2011


Fixed: Modifier keys weren't auto-released when sending special chars.

Fixed: Scancode/modifier-key mapping conflicts such as sc1xx vs ^sc0xx.

Fixed: $ and #UseHook had no effect if used only on the second or subsequent instance(s) of a hotkey.

Fixed: Potential crash when returning a value from a __Delete meta-function.

Fixed: "Uninitialized variable" warnings were triggered by the debugger.

Changed: base.Method() no longer triggers a default meta-function or a warning.

Changed: Gui +(Ex)Style no longer hides/shows the Gui.

Changed the debugger to report type="undefined" for uninitialized variables.

Added check to avoid incorrectly sending keystrokes for characters which actually require the "hankaku" key.
Added support for integers as class variable names.

Added "Static" keyword for declaring class variables.

1.1.00.00 - May 1, 2011

New features:

Implemented basic class definition syntax.

Implemented the new keyword for creating a derived object.

Added Func() for retrieving a reference to an existing function and improved IsFunc to recognize function references.

Added support for ++ and -- with object fields, such as x.y[z]++.

Changes:

Changed __Delete to not trigger __Call.

Changed OnClipboardChange to use AddClipboardFormatListener when available (i.e. on Windows Vista and later) to improve reliability.

Auto-concat with ( is more selective, so some invalid expressions like 12(34) will no longer work.
Fixes:

Fixed SetTimer Label, -0 to be treated as "run-once, very soon".

Fixed A_MyDocuments etc. to use SHGetFolderPath instead of undocumented registry keys.

Fixed non-empty ExcludeText causing windows with no text to be excluded.

1.0.97.02 - April 14, 2011

Fixed misinterpretation of comma as an arg delimiter when enclosed in {} in an expression.

Fixed For-loop to set A_Index only after the Expression arg is evaluated, so that the outer loop's value can be used.

Fixed default script location to be based on the directory containing the EXE (as documented), not the working directory.
Improved load-time validation to detect invalid attempts to jump out of a function with Goto.

1.0.97.01 - April 2, 2011

Fixed the 64-bit build to not truncate HWNDs or SendMessage/PostMessage params to 32 bits.
Fixed */:: being treated as an invalid hotkey (broken since L54).

Fixed the icons.

1.0.97.00 - March 28, 2011


Added {key: value} as syntax sugar for Object("key", value).

Added [x, y, z] as syntax sugar for Array(x, y, z), which is a new function equivalent to Object(1, x, 2, y, 3, z).
Added slight optimization: resolve any reference to True, False, A_PtrSize or A_IsUnicode in expressions at load-time.

Fixed hotkey parser to treat x & ^y as an error instead of ignoring ^.

1.0.96.00 - March 21, 2011

New features:

ComObjQuery: Queries a COM object for an interface or service.

ComObjFlags: Retrieves or changes flags which control a COM wrapper object's behaviour.

ComObjCreate allows non-dispatch objects to be created if an interface identifier (IID) is given.

COM arrays support for-loops and the Clone() method.

ListVars shows the inner variant type and value of each COM wrapper object, in addition to the wrapper's address.

Changes:

When a literal integer or variable containing both a numeric string and cached binary integer is assigned to a field of an object, an integer is stored instead of a string. This particularly benefits scripts calling COM methods which accept integers but not strings, or have
different behaviour depending on the type of value.

NULL values are now allowed with ComObjParameter for the VT_UNKNOWN and VT_DISPATCH types.

Improved support for Common Language Runtime (.NET) objects via COM.

FileRecycle should now warn before deleting a file which is too large to recycle.

When a SafeArray created with ComObjArray is assigned to an element of another SafeArray, a separate copy is created. This prevents the script from crashing due to a second attempt at "destroying" the array. ComObjFlags allows this behaviour to be avoided.

Fixes:

Assigning to a COM array of VT_DISPATCH or VT_UNKNOWN crashed the script.

Break and Continue were tolerated outside of loops in some cases.

Standalone carriage-return (`r) was not correctly interpreted as end-of-line.

MouseMove miscalculated negative coordinates with the Input and Event send modes.

Selecting Edit This Script from the tray menu or using the Edit command crashed the script (broken by v1.0.95).
Error dialogs pointed at irrelevant lines of code in some cases.

1.0.95.00 - March 12, 2011

All file I/O has been heavily optimized.

Added #Warn to assist with debugging; initial design by ac.

By default, if name_var contains a function name, name_var.() calls the function. This can be overidden via the default base object, as before.

Run supports verbs with parameters, such as Run *RunAs %A_ScriptFullPath% /Param.

If an operator which can accept either one operand (&x) or two numeric operands (x & y) follows a quoted literal string, auto-concat
occurs and the operator is applied only to the right-hand operand. This is because quoted literal strings are always considered non-
numeric and are therefore not valid input for numeric operators. For example, expressions like "x" &y and "x" ++y now work.

Fixed:

Wildcard hotkeys were not respecting modifiers such as ^!+ in specific cases.
File.Pos returned garbage for non-seeking file types; now it returns -1.
File.AtEOF was incorrectly true in some cases.

COM wrapper objects left A_LastError unset in some cases.


Gui submenu icons did not work on Windows 2000/XP/Server 2003.

SplashImage clipped the image if height > width.

ComObjConnect did not alert when the first parameter is invalid.

SplashImage now uses GDI+ only when the other methods fail, for compatibility.

Tilde in ~x:: now affects x & y:: in the same way that ~x & z:: would, instead of having no effect.

A_PriorHotkey and A_TimeSincePriorHotkey now have the expected values when used with #If.

RegExReplace did not advance through the string correctly after a match failure if the string contained non-ASCII characters.

1.0.92.02 - January 19, 2011

Fixed a memory leak which occurred when the return value of an object invocation or built-in function was not used, such as
file.ReadLine() or SubStr(x,y,z) alone on a line.

Replaced the fix from v1.0.92.01 with a better fix, which also fixes k::MsgBox(),x:=y and doesn't break if().
1.0.92.01 - January 18, 2011

Changed: FileCreateDir now sets A_LastError.

Fixed: GuiControl() or similar was sometimes misinterpreted as a command.
1.0.92.00 - January 13, 2011

Added support for compound assignments with objects, such as x.y += z.

Improved IniWrite in Unicode builds to prevent an empty line from appearing at the top of each new file.
Improved the parser to be more permissive about what can follow {/}/Else, especially when combined.
1.0.91.05 - January 1, 2011

Fixed: Cleanup code in COM method calls was freeing the wrong parameters.
Fixed (ANSI): DllCall set incorrect length for WStr parameters on output.
Fixed: Variadic function calls were unstable when param object was empty.
1.0.91.04 - December 29, 2010

Fixed (Unicode): RegExReplace omitted all text up to StartingPosition (broken by v1.0.90.00).
1.0.91.03 - December 27, 2010

Fixed: RegEx callout subpattern vars - broken by v1.0.90.00.
1.0.91.02 - December 26, 2010

COM: Added protection against NULL IDispatch/IUnknown pointers.

COM: Skip QueryInterface for IDispatch if VT_DISPATCH is passed explicitly.

Minor fix for maintainability: obj.field := var now correctly yields SYM_STRING, not SYM_OPERAND.
1.0.91.01 - December 24, 2010

Fixed: Unexpected results with File.Write(Str) after text-reading.

Fixed: UTF BOM check caused unexpected results in files without a BOM.

Fixed (ANSI): Parsing loops and File.ReadLine() treated Chr(255) as EOF.

Fixed (Unicode): RegExReplace errors where the UTF-8 and UTF-16 lengths differed.
Fixed: Disabling the last hook hotkey breaks Input.

Added: Simple optimization for RegExMatch/Replace.


1.0.91.00 - December 21, 2010

All changes in this release are COM-related.

Added: ComObjError now returns the previous setting.

Added: ComObjType(co) and ComObjValue(co).

Added: ComObjMissing().

Added: ComObjArray() and basic SAFEARRAY support.

Added: "Take ownership" parameter for ComObjParameter().

Changed: Values passed to COM functions via ComObjParameter are no longer freed in the process of calling the function.
Changed: ComObj.x() now falls back to PROPERTYGET if member 'x' is not found. This fixes for-loops for some objects.
Changed: Wrap unhandled variant types in an object rather than returning integer value.

Changed: Manage VT_UNKNOWN/VT_ARRAY lifetime automatically, by default.

1.0.90.00 - November 27, 2010

Fixed: UrlDownloadToFile in Unicode builds on Windows < 7.

Fixed: Upper-ANSI characters were sent as Alt+0 in ANSI build.

Fixed: File.Pos was incorrect after attempting to read past EOF.

Fixed: Escape sequences in #If expressions and static initializers.

Fixed: ClipboardAll sometimes crashed the script with certain formats.

Fixed: Transform HTML calculated length incorrectly for &#NNN; entities.
Fixed: VarSetCapacity now correctly ignores #MaxMem for ByRef variables.
Fixed: FileAppend,,file.txt set ErrorLevel=1 even on success.

Fixed: Match length was miscalculated for RegEx callouts with the P) option.
Integrated Sean's improvements to number handling in COM interop.
Optimized RegExReplace and RegExMatch in Unicode builds.

Revision 61 - October 3, 2010

Added: ObjClone(Object), forgotten when Object.Clone() was implemented.

Added: Support for RegEx Unicode properties in Unicode builds. Also upgraded PCRE to 8.10.

Added: Object.Remove(int, "") removes Object[int] without affecting other keys.

Changed: ComObj.xyz() is now always treated as a method-call.

Changed: Var := 123 is now left as an expression, for consistency. This makes Var := 123 and Var := (123) equivalent, whereas previously the former assigned only a string and the latter assigned both a string and a cached binary integer. In particular, this avoids some confusing type mismatch errors with COM objects.

Fixed: Dynamic variadic calls to functions with mandatory parameters.

Fixed: The final parameter of an assume-global variadic function had to be explicitly declared local.
Fixed: Static initializers interfering with setting of breakpoints.

Fixed: More pointer size-related errors with PCRE callouts on x64 builds.

Fixed: Input with 'M' option treated Ctrl-M (`r) as Ctrl-J (`n).

Fixed: Object.Remove(n) returned 0 (not "") if Object[n] didn't exist.


Revision 60 - September 24, 2010

Added: File.Encoding for changing or retrieving the codepage in use by a File object.

Added: Variadic functions and function-calls and indirect mode for callbacks.

Added: Object.Clone()

Changed: ByRef parameters no longer require the caller to supply a variable.

Changed: Obj.foo := "" now frees foo's contents as originally intended (but still doesn't remove the field).

Changed: OnMessage functions now tolerate optional and ByRef parameters.

Changed: RegisterCallback now enables execute access on callbacks in 32-bit builds (already did in 64-bit builds).

Changed: RegisterCallback now treats explicit ParamCount="" as omitted.

Fixed: For-loop was treating non-expression "0" as true for scripted enumerators.

Fixed: ComEvent (ComObjConnect) not working on the ANSI build.

Fixed: ComEvent (ComObjConnect) not correctly backing up/restoring local vars when calling a function which is already running.
Fixed: Buffer overflow in A_EndChar when there is no end char.

Fixed: Func->mNextFunc not inititialized to NULL (used only by LowLevel scripts).

Debugger: Added the capability to retrieve an object's contents (with a supported debugger client).

Debugger: Fixed a few bugs.

Revision 59 - September 12, 2010

Fixed: #If expression should now evaluate each expression at most once per keypress in all cases.

Changed: SplashImage uses common image-loading routines; now supports PNG and similar, but results may differ from before for icon files.

Added: For x,y in z.

Added: Loop .. Until expression, usable with any Loop or For-loop.

Added: Named loops; continue outer_loop, break 2, etc.

Debugger: Encode stdout and stderr packets as UTF-8.

Debugger: Allow user to Abort, Retry or Ignore when the initial connection fails.

Debugger: Allow attaching a debugger client by sending the script a registered window message.
Debugger: Allow detaching debugger client by sending the "detach" DBGp command.
Revision 58 - September 5, 2010

Added: static var := expression.
Revision 57 - September 4, 2010

Fixed Str*, WStr* and AStr* DllCall return types on x64.

Added functionality to InStr to bring it in line with StringGetPos:

If StartingPos is negative, the search is conducted right-to-left beginning at that offset from the end.
An additional parameter is available to specify which occurrence of the string to find.

Added #include <LibName> for explicitly including a script from a function library folder.
Added functionality to IniRead and IniWrite allowing an entire section to be read or written.
Added functionality to IniRead allowing a list of section names to be retrieved.


Added support for custom verbs to Run/RunWait: Run *verb file.

Made improvements to the way Run/RunWait extracts the action and its parameters from the Target parameter.
Changed NumGet/NumPut to allow Offset to be omitted entirely since Type is always non-numeric.

Removed the restriction that a label can't point to the end of a block.

Revision 56 - August 29, 2010

Added support for x64 compiled scripts. Requires Ahk2Exe_L and x64 AutoHotkeySC.bin.
Fixed: Deref operator (*addr) rejected addresses outside 32-bit range.

Fixed: #If expression memory allocation error on x64.

Fixed: Custom hotstring end chars with code points greater than U+00FF.

Fixed: Special characters being sent out of sequence by SendInput/Play.

Fixed: */ being discarded in continuation sections (see L54).

Revision 55 - August 19, 2010

Fixed: GroupActivate not setting ErrorLevel=1 if no Label was specified.

Fixed: Tab controls in x64 build.

Fixed: String-copy mode of StrPut when length is omitted; broken by L53.

Fixed: Data-alignment issues in x64 builds.

Changed: Set A_LastError for more File* commands to assist debugging.

Includes FileAppend, FileRead, FileReadLine, FileDelete, FileCopy, FileMove, FileGetAttrib/Time/Size/Version and
FileSetAttrib/Time.

Excludes FileCopyDir, FileRecycle, FileMoveDir, FileRemoveDir, FileRecycleEmpty, FileCreateDir and FileInstall as the APIs used do not consistently set or return a Win32 error code.

Revision 54 - August 15, 2010

Fixed: RunAs in Unicode build. [jackieku]

Fixed: RegisterCallback in x64 build. [fincs]

Fixed: Executables failing to run on Win2k and WinXP prior to SP2. Win2k requires SP4 and updates (probably KB 816542). XP not
tested.

Fixed: Dialogs such as MsgBox became unresponsive when interrupted by another script thread. Message filter/workaround added in
L45 had to be removed.

Fixed: Multi-byte characters in default ANSI codepage; this was also causing a memory leak.
Fixed: ComObject now allows purely numeric property/method names.

Enhanced usability and capabilities of FileOpen/File object.

FileOpen's Flags parameter accepts a human-readable string of flags.

FileOpen's "update" mode has been renamed "read/write" and now creates the file if it didn't already exist.
FileOpen sets A_LastError as appropriate.

File := FileOpen(handle,"h") wraps an existing file handle in an object.

File.Seek(n) defaults to SEEK_END when n is negative.

File.Pos (or File.Position) can be used in place of Tell and Seek.

File.Pos, File.Length, File.AtEOF and File.__Handle can be used without empty parentheses().
File.Length can be set, as in File.Length:=n.

File.ReadNum() and File.WriteNum(n) read or write a number, where Num is a NumGet-compatible type name.
File.WriteLine(s) is equivalent to File.Write(s "`n"), for symmetry with File.ReadLine().

File.Read() reads and returns the remainder of the file when used without parameters.

File object now returns "" for unrecognized methods and invalid syntax rather than the numeric address of "".


Changed: GroupAdd's Label parameter now applies to the whole group. [Discussion]
Changed: GroupActivate sets ErrorLevel on success/failure. (Same thread as above.)
Changed: */ at the beginning of a line is ignored if there was no /*. [Discussion]

Removed ToCodePage and FromCodePage subcommands of Transform.
Revision 53 - August 8, 2010

Merged AutoHotkey64 - COM support and x64 compatibility.
x64 (changes since AutoHotkey64):

Fixed floating-point return values and exception handling for DllCall.
Fixed RegEx callouts.

Re-enabled GetProcAddress optimisation for DllCall.

NumPut and NumGet default to "Int64" in x64 builds.

COM (changes since AutoHotkey64):

Allow ComObjParameter to wrap 64-bit values in 32-bit builds.

Implemented more standard ref counting conventions in ComObjActive.
Prevent extraneous AddRef for new ComObjects in certain cases.

Don't treat pdispVal==NULL return value from Invoke as an error.

Fail more predictably when given wrong type of object.

Require explicit second param in ComObjType, don't assume "IID".
Free local vars after ComEvent calls a function.

Remove pVarResult param from ComEvent; use return value instead.
Pass the original wrapper ComObject in each ComEvent call.

Add context to ComError dialog; let the buttons make more sense.

Implemented common syntax validation code for enumerators. Enum[] and Enum.Next() are now supported with or without parameters. Enum[]:=val and similar obscure forms which worked in AutoHotkey_COM/AutoHotkey64 are not allowed.

"Ptr" type is still signed (unlike AutoHotkey64), for maximum flexibility and consistency.

Other changes:

Added: Object.HasKey(key).

Added: Object(obj) increments obj's reference count and returns its address.

Added: ObjAddRef() and ObjRelease().

Fixed: A_ThisHotkey now has the expected value when used with #If.

Fixed: RunAs in Unicode build (fixed by jackieku).

Changed: Default script codepage for ANSI builds is now CP0 (ANSI).

Changed: x.y[] is now equivalent to (x.y)[] rather than x["y"].

Changed: Built-in methods can now be called with or without the underscore prefix (e.g. obj.MaxIndex() or obj._MaxIndex()).
Revision 52 (again) - July 10, 2010

Added support for built-in and environment variables in double-derefs.

Improved support for multi-byte characters in certain codepages (previously only 932, 936, 949, 950 and 1361 were supported).
Fixed: StrPut failed for codepages which don't support WC_NO_BEST_FIT_CHARS, such as UTF-7.

Fixed: Double-deref as object - literal%var%.literal.

Fixed: StrPut("", Encoding) null-terminated an invalid address.

Revision 52 - June 12, 2010

Fixed: ObjRemove's Key parameter is now optional, as with Object._Remove.


Fixed: Files were improperly locked while reading, unlike in older versions.
Fixed: Uppercase Hex format caused negative integers to become unsigned.
Fixed: RegExMatch was corrupting output array items when specific conditions were met. See bug report.

Revision 51 - April 11, 2010

Changed: Use <EXENAME>.ahk instead of AutoHotkey.ini or AutoHotkey.ahk.
Changed: Default to UTF-8 for script files; override with /CPnnn.

Fixed: Unpause when the script exits so that object __Delete meta-functions can run.
Revision 50 - March 27, 2010

Improved flexibility of Object._Insert.

Object._Insert(x) - inserts x at _MaxIndex()="" ? 1 : _MaxIndex() + 1.

Object._Insert(i,x,y,z) - inserts x,y,z at i,i+1,i+2.
Improved flexibility of Object._Remove.

Object._Remove(k) - removes and returns the value associated with k.
Object._Remove() - removes and returns the value at _MaxIndex().

Added file share mode flags to FileOpen [by jackieku].

Fixed: 'P' option of RegExMatch incorrectly output 1 for subpatterns which did not match anything.
Fixed: Object._SetCapacity(key,n) was not null-terminating in some cases.

Fixed: StatusBarGetText returned only half of the text in Unicode builds.

Revision 49 - March 14, 2010

Added obj._NewEnum().

Added ObjMethod(obj) for each built-in obj._Method().

Changed: ObjSet/Get/Call can no longer be called/overridden by script.

Fixed: Potential crash caused by VK_PACKET check added in L48.

Fixed: Character codes in VK_PACKET events were potentially misinterpreted as scancodes.
Fixed: ExcludeText was ineffective after the first matching control.

Revision 48 - February 21, 2010

Fixed: Standalone obj.() was not recognized as a valid expression.

ControlSend now uses WM_CHAR to support characters which have no associated keycode. For instance, this applies to "…" (en-US), "∞" in a Unicode build and {U+221e} in either build.

KeyHistory now shows the full 16-bit character code for VK_PACKET (VK=E7) events. Send may indirectly cause these to be
generated for Unicode characters.

Revision 47 - February 13, 2010

Fixed (Unicode): ControlGet,List with ListView controls.
Revision 46 - February 11, 2010

Added A_FileEncoding, which returns the current default file encoding.
Added StrPut and extended StrGet with additional features.


Revision 45 - February 8, 2010

Added _GetAddress; _SetCapacity/_GetCapacity may now operate on a given field. [more info]
Added workaround for WM_PAINT infinite loop often caused by subclassing.

Allow obj.() as a means to call the default method of an object; equivalent to obj[""]().

Dev: Added solution and project files for MSBuild 4.0 & VS2010. [more info]

Fixed (Unicode): 'Running' column in ListHotkeys.

Revision 44 - February 7, 2010

Fixed: Attempting to set "nothing" crashed the script. For instance, x[]:=z.

Fixed (Unicode): Unable to find default script (Documents\AutoHotkey.ahk).

Fixed (Unicode): A_Desktop, A_ProgramFiles and several other built-in variables which read their value from the registry caused strings to be incorrectly terminated.

Fixed (ANSI): Characters in the range 0x80-0xFF couldn't be found by InStr or StringReplace.
Changed (ANSI): Treat ToCodePage/FromCodePage like other unsupported/invalid subcommands.
Revision 43 - January 29, 2010

Fixed: obj.Func() resulting in a random integer when it should be an empty string.
Revision 42 - January 28, 2010

Merged with AutoHotkeyU.

Numerous bug-fixes and improvements, some relating to the merge.
Revision 41 - December 20, 2009

Fixed: Floating-point numbers were equivalent to an empty string when used as keys in objects. They are now converted to numeric
strings in the current float format, as originally intended.

Revision 40 - December 13, 2009

Changed meta-functions and multi-param behaviour to improve flexibility. Meta-functions are now invoked *before* searching for an
appropriate field in each base object; however, values in x.base will override meta-functions defined in x.base.base. Chaining meta-
functions (inheritence) is now possible by avoiding "Return"

Improved Default Base functionality to be more consistent with real objects.

Changed (Debugger): While stepping through code, skip all braces except those which end a function.

Changed (Debugger): When stepping onto the hidden "Exit" at end of the script, consider it to be *below* the last physical line to avoid confusion.

Revision 39 - December 2, 2009

Fixed (Debugger): Error in Base64 decoding used by property_set.
Revision 38 - November 17, 2009

Added: #MenuMaskKey directive to change which key is used to mask Alt/Win keyup events. See this thread for background
information.

Changed: If x[1,2]:=3 creates an object for x[1], it's base is no longer automatically set to x.base. See the documentation for a method of controlling this behaviour.

Revision 37 - November 7, 2009


Added: Support for obj[method_name](params) object-call syntax.
Revision 36 - November 4, 2009

Changed: If x.y or similar is immediately followed by an open-bracket ([), the right-most identifier preceding the bracket is treated as
the first parameter of the operation. For instance, a.b.c[d] is equivalent to ObjGet(a.b,"c",d) and x.y[z]:=v is equivalent to
ObjSet(x,"y",z,v). Previously each sub-expression preceding a bracket was evaluated separately.

Changed: If a method-call such as x.y() is followed immediately by an assignment, the parentheses are treated as brackets. For instance, x.y(z):=v is now equivalent to ObjSet(x,"y",z,v).

Fixed: If(expr) and While(expr) with no delimiting space or comma.
Revision 35 - October 25, 2009

Fixed: Standalone expressions beginning with two or more "dots", such as x.y.z(). (Broken by L34.) Note that '(' or '[' or ':=' is still
required.

Revision 34 - October 24, 2009

Changed: Setting a value within an object to an empty string now stores the empty string rather than removing the key-value pair from
the object. _Remove can still be used to completely remove key-value pairs.

Changed: Command names must be terminated with a space, tab or comma. The following characters no longer bypass this requirement: <>:+-*/!~&|^[]. For instance, syntax errors such as MsgBox< foo and If!foo are now caught at load-time.

Fixed: Return now properly handles expressions which result in a variable containing an object. For instance, Return x:=y, Return (x), Return x,... and similar should work now (Return x already worked).

Fixed: Multi-parameter get/set did not correctly support meta-functions for multiple objects (such as for x and x[y] in the expression
x[y,z]).

Fixed: Cascading object-assignments such as the x[y]:=z in r:=x[y]:=z could not yield numbers or objects - broken by L33.
Fixed: x._Remove(y) crashed the script or removed the wrong item if x did not contain y.

Fixed: x.=y, if x.y=... and similar. May affect other expressions.

Fixed: Standalone ternary expressions no longer requires spaces. For instance, x? F(1) : F(2) is now allowed.

Debugger: On script exit, disconnect debugger *after* releasing objects to allow debugging of __Delete handlers.
Revision 33 - October 3, 2009

Fixed: Local variables were not automatically freed for functions which return objects or pure numbers.

Fixed: Two separate reference-counting errors related to ternary operator and Object().

Fixed: If a string returned by a scripted object function was assigned directly to a variable, the variable's length was set incorrectly.
Fixed: If the last operation in an expression retrieved a string from a temporary object, the object and string were freed prematurely.
Fixed: Numeric strings with special formatting were not preserved when returned from a function via a variable or passed to a recursive function.

Fixed: If the final result of an expression (other than for Return) is an object, correctly yield an empty string instead of silently aborting
the thread.

Fixed: __Delete meta-functions sometimes overwrote temporary values in the deref buffer.

Added: An address retrieved via &object may be cast back into an object reference by using Object(address).
Revision 32 - September 26, 2009

Fixed: Send/PostMessage crash when less than three parameters were specified.
Revision 31 - September 26, 2009


Added: Object/array support and numerous minor changes to make this possible.

Added: Support for While(expression) with no delimiting space.

Added: Trim, LTrim, RTrim.

Added: A ~= B; equivalent to RegExMatch(A, B). May be removed in a future revision.

Fixed: An incompatibility with LowLevel.

Changed: Characters [, ] and ? are no longer valid in variable names. Consequently, ? (ternary) no longer requires a space on either side. Changed: Optional parameters may now be omitted at any position in the parameter list of a non-dynamic function call. Since this works by automatically inserting the parameter's default value at load-time, it is not supported or allowed for dynamic function-calls.

Debugger: Various minor changes to make program flow easier to follow while stepping through code.

Optimization: If DllCall's first parameter is a literal string which identifies a function already present in memory, it is replaced with the actual address of the function.

Updated from v1.0.48.03 to v1.0.48.04.
Revision 30 - May 31, 2009

Updated from v1.0.48.02 to v1.0.48.03.
Revision 29 - May 2, 2009

All supported image formats may now be used as menu icons. Currently it is necessary to specify "actual size" when setting the icon to preserve transparency on Windows Vista and later. For example:

Menu, Icon, MenuItemName, Filename.png,, 0
Revision 28 - May 2, 2009

Improved average-case performance of dynamic function calls by implementing binary search for function name look-ups. This change also applies to other areas, such as load-time resolution of function references in expressions and run-time resolution by OnMessage,
RegisterCallback, etc.

Revision 27 - April 26, 2009

Updated from v1.0.48.00 to v1.0.48.02.
Revision 26 - April 11, 2009

Fixed: Menu icons were not drawn on items which have sub-menus if owner-drawing was in use.

Fixed: Menu icons were not freed if all menu items were deleted at once.

Changed (Source): Renamed AutoHotkey.sln to AutoHotkey_L.sln to allow VS window to be identified more easily.
Revision 25 - March 30, 2009

Fixed: Send {U+xxxx} correctly sets modifier key-state as with any normal key.
Fixed: Send {U+..xx} no longer triggers hotkey SCxx.

Revision 24 - March 30, 2009

Added: Support for Send {U+xxxx}. SendInput() is used where available for proper unicode support, otherwise falls back to
Alt+Numpad.

Revision 23 - March 30, 2009

Fixed: GuiControl, Enable/Disable now only resets focus if the focused control was disabled.


Revision 22 - March 26, 2009

Optimized If var [not] in/contains MatchList, especially for long lists containing shorter fields.
Revision 21 - March 16, 2009

Minor optimizations to While. [thanks Chris]

Fixed (Debugger): Revisions 19 and 20 omitted timer threads from the call stack.

Fixed (Debugger): XML-reserved characters were not escaped in most situations.

Fixed (Debugger): Incorrect command and transaction_id were used in the final response before exiting the script.
Revision 20 - February 27, 2009

Changed: If an icon cannot be loaded with the new method, fall back to the old method.
Revision 19 - February 26, 2009

Added: Gui, Font, qN option to set font quality/control anti-aliasing, where N is between 0 and 5.

Fixed: IL_Add now loads icons at the most appropriate size when multiple sizes exist.

Merged with AutoHotkey v1.0.48, introducing bug fixes, optimizations and other changes by Chris. Some AutoHotkey_L features were integrated into the mainstream release; changes to these features since previous revisions are as follows:

Legacy behaviour is no longer applied to While - e.g. "While %x%" is correctly interpreted as a double-deref rather than as "While
x".

One-True-Brace style is now supported for While.

Static vars may now be declared and initialized in assume-static functions.

Passing too few parameters in a dynamic function call is no longer allowed, as it allows the function's caller to second-guess the
function's designer, reduces the ability to detect script bugs at runtime, and may cause the application to crash if calling a built-in
function.

Revision 18 - February 21, 2009

Fixed: Incomplete bug-fix in previous revision causing concat followed by assignment to skip the rest of the expression in some cases.
Revision 17 - February 20, 2009

Added: Menu icons via Icon and NoIcon sub-commands of the Menu command.

Changed: Negative icon numbers can now be used to indicate a resource ID within an executable.

Changed: Set default style of menus to include MNS_CHECKORBMP.

Changed: Load both small and large versions of custom tray icons to allow the correct icons to be shown in the appropriate places.
Fixed: Loading of icons from executable files at sizes other than the system small/large.

Revision 16 - February 4, 2009

Fixed: Deleting a menu item partially deleted its associated sub-menu.
Revision 15 - February 1, 2009

Fixed: SetFormat's presence in a *compiled* script was not disabling binary number write-caching. SetFormat should now work
correctly in compiled scripts.

Revision 14 - February 1, 2009

Numerous bug-fixes and optimizations by Chris (pre-v1.0.48 beta).
Added: Support for regex callouts and the auto-callout option 'C'.


Changed: A_AhkVersion now includes the revision number. For instance, this is 1.0.47.07.L14.

Fixed: HWND's/window ID's were sign-extended to 64-bit. For instance, 0xb482057e became 0xffffffffb482057e.
Revision 13 - November 29, 2008

Fixed: Invalid DllCall types were treated as INT in some build environments.

Added: Workaround for GuiEscape issue when disabling focused control.

Changed version info: InternalName, ProductName and FileDescription are now "AutoHotkey_L" instead of "AutoHotkey".
Revision 12 - September 6, 2008

Fixed: Potential access violation when using property_get on a built-in variable. -- DBGP
Revision 11 - September 5, 2008

Fixed: Remove checksum from AutoHotkeySC.bin via post-build script (AutoHotkey must be installed).
Added: .L suffix to A_AhkVersion.

Added: Preliminary support for DBGp (interactive debugging).

Revision 10 - August 2, 2008

Fixed: WheelLeft/WheelRight support, which was broken in revision 9.
Revision 9 - July 29, 2008

Fixed: Allow Break/Continue in While.

Fixed: TrayTip in non-English Windows and possibly other side-effects of using Vista headers.
Revision 8 - July 27, 2008

Added: #IfTimeout directive to set the timeout for evaluation of #If expressions, in milliseconds. Default is 1000.
Added: Assume-static mode for functions. "Static" must precede any local/global variable declarations.

Added: One-true-brace support for While.

Changed: While now sets A_Index to the iteration about to begin.

Revision 7 - July 26, 2008

Added: IsFunc(FuncName) - Returns a non-zero number if FuncName exists in the script or as a built-in function.
Revision 5 - July 19, 2008

Cleaned up obsolete references to test scripts.
Added basic default test script.

Revision 4 - July 18, 2008

Added: #if (expression) - Similar to #IfWinActive, but for arbitrary expressions.

Added: WheelLeft, WheelRight - Support for WM_MOUSEHWHEEL, which was introduced with Windows Vista. (Requires Vista.) Added: While, expression - Loop while a condition is true.

Added: A_IsPaused - True if the underlying thread is paused.

Added: A_IsCritical - True if the current thread has been marked uninterruptible by the "Critical" command.


Changed: Allow any number of parameters to be passed in dynamic function calls. Fixed: Access Violation caused by WinGetClass and subclassed windows.

Fixed: Access Violation caused by empty dynamic function references.


Debugging Clients

Additional debugging features are supported via DBGp, a common debugger protocol for languages and debugger UI communication. See Interactive Debugging for more details. Some UIs or "clients" known to be compatible with AutoHotkey are listed on this page:

SciTE4AutoHotkey
XDebugClient
Notepad++ DBGp Plugin
Script-based Clients
Command-line Client
Others

SciTE4AutoHotkey

SciTE4AutoHotkey is a free, SciTE-based AutoHotkey script editor. In addition to DBGp support, it provides syntax highlighting,
calltips/parameter info and auto-complete for AutoHotkey, and other useful editing features and scripting tools.

Debugging features include:
Breakpoints.

Run, Step Over/Into/Out.

View the call stack.

List name and contents of variables in local/global scope.
Hover over variable to show contents.

Inspect or edit variable contents.

View structure of objects.

http://fincs.ahk4.net/scite4ahk/
XDebugClient

XDebugClient is a simple open-source front-end DBGp client based on the .NET Framework 2.0. XDebugClient was originally
designed for PHP with Xdebug, but a custom build compatible with AutoHotkey is available below.

Changes:

Allow the debugger engine to report a language other than "php".

Added AutoHotkey syntax highlighting.

Automatically listen for a connection from the debugger engine, rather than waiting for the user to click Start Listening.
Truncate property values at the first null-character, since AutoHotkey currently returns the entire variable contents and
XDebugClient has no suitable interface for displaying binary content.

Download: Binary; Source Code (also see SharpDevelop, Dockpanel Suite and Advanced TreeView.)
Usage:

Launch XDebugClient.

Launch AutoHotkey /Debug. XDebugClient should automatically open the script file.

Click the left margin to set at least one breakpoint.

Choose Run from the Debug menu, or press F5.

When execution hits a breakpoint, use the Debug menu or shortcut keys to step through or resume the script.

Features:

Syntax highlighted, read-only view of the source code.

Breakpoints.

Run, Step Over/Into/Out.

View the call stack.

Inspect variables - select a variable name, right-click, Inspect.

Issues:

The user interface does not respond to user input while the script is running.
No mechanisms are provided to list variables or set their values.

Notepad++ DBGp Plugin

A DBGp client is available as a plugin for Notepad++. It is designed for PHP, but also works well with AutoHotkey.


Download: See DBGp plugin for Notepad++.
Usage:

Launch Notepad++.

Configure the DBGp plugin via Plugins, DBGp, Config...

Note: File Mapping must be configured. Most users will not be debugging remotely, and therefore may simply put a checkmark
next to Bypass all mapping (local windows setup).

Show the debugger pane via the toolbar or Plugins, DBGp, Debugger.
Open the script file to be debugged.

Set at least one breakpoint.

Launch AutoHotkey /Debug.

Use the debugger toolbar or shortcut keys to control the debugger.

Features:

Syntax highlighting, if configured by the user.

Breakpoints.

Run, Step Over/Into/Out, Run to cursor, Stop.

View local/global variables.

Watch user-specified variables.

View the call stack.

Hover over a variable to view its contents.

User-configurable shortcut keys - Settings, Shortcut Mapper..., Plugin commands.

Issues:

Hovering over a single-letter variable name does not work - for instance, hovering over a will attempt to retrieve  a or a .
Hovering over text will attempt to retrieve a variable even if the text contains invalid characters.

Notepad++ becomes unstable if property_get fails, which is particularly problematic in light of the above. As a workaround,
AutoHotkey sends an empty property instead of an error code when a non-existent or invalid variable is requested.

Script-based Clients

A script-based DBGp library and example clients are available from GitHub.
dbgp_console.ahk: Simple command-line client.

dbgp_test.ahk: Demonstrates asynchronous debugging.

dbgp_listvars.ahk: Example client which justs lists the variables of all running scripts.

GitHub: Lexikos / dbgp

The DebugVars script provides a graphical user interface for inspecting and changing the contents of variables and objects in any
running script (except compiled scripts). It also serves as a demonstration of the dbgp.ahk library.

GitHub: Lexikos / DebugVars
Command-line Client

A command-line client is available from xdebug.org, however this is not suitable for most users as it requires a decent understanding of DBGp (the protocol).

Others

A number of other DBGp clients are available, but have not been tested with AutoHotkey. For a list, see Xdebug: Documentation.


AutoHotkey_L New Features

This document describes features added in the AutoHotkey_L branch of AutoHotkey development, now simply known as "AutoHotkey 1.1".

Caution: This document has been neglected in recent years and may be missing some of the more recent changes.
Control Flow

Break LoopLabelBreak out of a loop or any number of nested loops.

Continue LoopLabelContinue a loop, even from within any number of nested loops.
For x,y in z                Loop through the contents of an object.

Loop Until                 Loop until a condition is true. Applicable to any type of Loop.
Try...Catch...FinallyProvides structured exception handling.
Throw                        Throws an exception.

Commands

FileEncoding                        Sets the default encoding for FileRead, FileReadLine, Loop Read, FileAppend, and FileOpen. 

See also: Text Encodings
Gui                                        See GUI Enhancements below.

IniRead/Write/Delete           Read, write or delete entire sections, or retrieve a list of all section names.

Menu, Icon                           Sets or removes a menu item's icon.

Run                                       Improvements were made to the way parameters are parsed.

SendInput {U+nnnn}           Sends a Unicode character. Unicode characters may be used directly in Unicode builds.
SendLevel                            Controls which artificial keyboard and mouse events are ignored by hotkeys and hotstrings.
SetFormat, IntegerFast, h|HSet lower-case or upper-case hexadecimal format.

SetRegView, RegViewAllows registry commands in a 32-bit script to access the 64-bit registry view and vice versa. 

Transform, HTML                Perform code page or HTML transformations.

WinGet, ..., ProcessPathRetrieves the full path and name of the process that owns a given window.

Directives

#If expressionSimilar to #IfWinActive, but for arbitrary expressions.

#IfTimeout          Sets the maximum time that may be spent evaluating a single #If expression.
#MenuMaskKeyChanges which key is used to mask Win or Alt keyup events.

#Include <Lib>Includes a script file from a function library folder.

#InputLevelControls which artificial keyboard and mouse events are ignored by hotkeys and hotstrings.
#Warn                 Enables or disables warnings for selected conditions that may be indicative of developer errors.

Functions

ComObj... --
ComObjActive
ComObjEnwrap/Unwrap
ComObjParameter
ComObjType


FileOpen                           Provides object-oriented file I/O.

Func                                 Retrieves a reference to a function.

GetKeyName/VK/SCRetrieves the name or text, virtual key code or scan code of a key.
InStr                                 Searches for a given occurrence of a string, from the left or the right.
IsByRef                            Determines whether a ByRef parameter was supplied with a variable.
IsObject                            Determines whether a value is an object.

StrPut / StrGet                  Copies a string to or from a memory address, optional converting it between code pages.
Trim                                  Trims certain characters from the beginning and/or end of a string.

RegEx (?CNum:Func)Calls a function during evaluation of a regex pattern.

Function Libraries            New "local library" and #Include <LibName>.

Variadic Functions           Functions may accept a variable number of parameters via an array.

Static Initializers               Static variables can now be initialized using any expression.

Objects

GeneralBehaviour and usage of objects in general.

ObjectAssociative arrays which can be extended with other functionality.
EnumeratorAllows items in a collection to be enumerated.

File              Provides an interface to access a file. FileOpen returns an object of this type.
Func            Represents a user-defined or built-in function which can be called by the script.
ComObjectSee ComObj functions above.

Variables

A_Is64bitOSContains 1 (true) if the OS is 64-bit or 0 (false) if it is 32-bit.

A_IsUnicode      In Unicode builds, this variable contains 1 (true). In ANSI builds it is not defined, so is effectively false. A_FileEncodingContains the default encoding for various commands; see FileEncoding.

A_OSVersionSupports Windows 7 and Windows 8; see A_OSVersion.

A_PriorKeyThe name of the last key which was pressed prior to the most recent key-press or key-release ... (More) A_PtrSize       Contains the size of a pointer, in bytes. This is either 4 (32-bit) or 8 (64-bit).

A_RegViewThe current registry view as set by SetRegView.

A_ScriptHwndThe unique ID (HWND/handle) of the script's hidden main window. 

Datatypes

Ptr              Equivalent to Int in 32-bit builds and Int64 in 64-bit builds. Supported by DllCall, NumPut and NumGet.
AStr, WStrSupported only by DllCall; see Script Compatibility.

Unicode

CompatibilityHow to deal with Unicode in DllCall, etc.
Script FilesUsing Unicode in script files.
SendInputUsing Unicode with SendInput.

Other

ahk_exe                   Windows can be identified by the name or path of the process (EXE file) which owns them.
Debugging               Interactive debugging features (line by line execution etc.).

Error HandlingTry/catch/throw and increased usefulness for A_LastError. 

GUI EnhancementsVarious enhancements to the Gui command and related.

Icon Support            Resource identifiers and improved support for various icon sizes.
Other ChangesChanges affecting script compatibility.

Version HistoryHistory of AutoHotkey_L revisions.

Error Handling


Many commands support using try/catch instead of ErrorLevel for error handling. For example:

try

{

    FileCopy, file1.txt, C:\folder
    FileDelete, C:\folder\old.txt

}

catch

    MsgBox An error occured!

Additionally, the following commands now set A_LastError to assist with debugging: FileAppend, FileRead, FileReadLine, FileDelete, FileCopy, FileMove, FileGetAttrib/Time/Size/Version, FileSetAttrib/Time, FileCreateDir, RegRead, RegWrite, RegDelete.

Function Libraries

In addition to the user library in %A_MyDocuments%\AutoHotkey\Lib and standard library in the AutoHotkey directory, functions may be auto-included from the "local library" which resides in %A_ScriptDir%\Lib. For more information, see Libraries of Functions.

#Include <LibName> explicitly includes a library file which may be located in any one of the function libraries.
GUI Enhancements

A number of enhancements have been made to the Gui command and related:

A name or HWND can be used instead of a number between 1 and 99 when referring to a GUI.

Gui, New creates a new anonymous GUI.

Any number of named or anonymous GUIs can be created.

New GUI options: +HwndOutputVar, +ParentGUI

A GUI's owner can be any arbitrary window: +Owner%HWND%.

Gui, Font can control anti-aliasing of text.

ActiveX controls such as the Internet Explorer WebBrowser control are supported.
GuiControlGet, OutputVar, Name gets the name of the variable associated with a GUI control.
Keyboard accelerators such as Ctrl+O are supported automatically when used in Gui menus.
Font quality can be controlled by the Font sub-command.

Static Variables

Static variables can now be initialized using any expression. For example:

Sleep 500

MsgBox % Time() "ms since the script started."
Time() {

    static Tick := A_TickCount

    return A_TickCount - Tick

}

Text Encodings

FileRead, FileReadLine, Loop Read and FileAppend support the majority of Windows-supported text encodings, not just the system
default ANSI code page. FileEncoding can be used to set the default encoding, which can be overridden for FileRead and FileAppend as follows:

FileRead, OutputVar, *Pnnn Filename
FileAppend , Text, Filename, Encoding

While nnn must be a numeric code page identifier, Encoding follows the same format as FileEncoding.
See also: Script Compatibility

Variadic Functions and Function-Calls

Variadic functions can receive a variable number of parameters via an array, while variadic function-calls can be used to pass a variable number of parameters to a function.

Improvements to Icon Support

Unusual Sizes

Icon resources of any size supported by the operating system may be extracted from executable files. When multiple sized icon resources exist within an icon group, the most appropriate size is used. Prior to revision 17, an arbitrary icon resource was selected by the system,


scaled to the system large icon size, then scaled back to the requested size.
Resource Identifiers

Negative icon numbers may be used to identify a group icon resource within an executable file. For example, the following sets the tray icon to the default icon used by ahk files:

Menu, Tray, Icon, %A_AhkPath%, -160


 

 


Version 1.1.30.00

https://autohotkey.com

©2003-2014 Chris Mallett, portions ©AutoIt Team and the AHK community

Software License: GNU General Public License
Quick Reference

Getting started:

How to use the program

Tutorial for beginners

Text editors with AutoHotkey support
Frequently asked questions

Scripts:

Concepts and conventions: explanations of various things you need to know.
Scripting language: how to write scripts.

Miscellaneous topics

Command and function list

Variables and expressions

Functions

Objects

Interactive debugging

Keyboard and mouse:

Hotkeys (mouse, joystick and keyboard shortcuts)

Hotstrings and auto-replace

Remapping keys and buttons

List of keys, mouse buttons and joystick controls

Other:

DllCall

RegEx quick reference

Script compatibility - AutoHotkey 1.0 users read this

Acknowledgements

A special thanks to Jonathan Bennett, whose generosity in releasing AutoIt v2 as free software in 1999 served as an inspiration and time- saver for myself and many others worldwide. In addition, many of AutoHotkey's enhancements to the AutoIt v2 command set, as well as the Window Spy and the old script compiler, were adapted directly from the AutoIt v3 source code. So thanks to Jon and the other

AutoIt authors for those as well.

Finally, AutoHotkey would not be what it is today without these other individuals.
~ Chris Mallett


Archived Changes

This document contains a history of changes made within the original branch of AutoHotkey development, by Chris Mallett.
For newer changes, see Changes & New Features.

1.0.48.05 - September 25, 2009

Fixed crash of SendMessage and PostMessage when wParam or lParam is omitted (broken by 1.0.48.04). [thanks Lexikos]
1.0.48.04 - September 25, 2009

Fixed StringSplit to work properly inside functions of compiled scripts (broken by 1.0.35.01). [thanks engunneer & Lexikos]

Fixed SendPlay not to wait for the release of the Windows key prior to sending an "L" keystroke (broken by 1.0.48.01). [thanks Lexikos] Fixed A_EndChar to be valid when the B0 option is present, and to be empty when there is no ending character (broken by 1.0.44.09).
[thanks Al2000]

Fixed FormatTime to yield a valid time of day even when the specified month is out-of-range (broken by 1.0.48.00). [thanks
silveredge78]

Fixed FileCreateDir to support a leading backslash even when it is the only backslash; e.g. \dir. [thanks jaco0646]

Fixed GuiControl/GuiControlGet/Gui/SendMessage to work reliably even when they trigger a callback or OnMessage function. [thanks Lexikos]

Fixed RegExMatch() not to produce too few replacements when an empty-string match is followed by a non-empty-string match.
Changed While() to be recognized as a loop rather than a function. [thanks Crash&Burn]

Improved UrlDownloadToFile to support FTP and Gopher. [thanks Lexikos]

Improved the stdout/asterisk mode of FileAppend to write immediately rather than lazily to standard output. [thanks Lexikos]
Added full support for if % expression. [thanks kenomby]

1.0.48.03 - May 3, 2009

Fixed ListLines On not to erase the most recent log entry in the line history. [thanks Lexikos]
Fixed ListView to respond properly to mouse dragging when timers are running. [thanks Solar]
Fixed key-up hotkeys so that if one is created while its key is being held down, the release of the key doesn't trigger the wrong hotkey.

[thanks Peter & engunneer]
1.0.48.02 - April 19, 2009

Changed and fixed Gosub and GroupActivate so that when a function calls an external/public subroutine, that subroutine will treat all
dynamic variables as globals, and will have outside-of-function GUI behavior. [thanks kenomby & Lexikos]

Improved performance of True/False/A_EventInfo in expressions by treating them as integers vs. strings.
1.0.48.01 - April 15, 2009

Changed: For Windows Vista and later, hotkeys that include the Win key (e.g. #a) will wait for LWin and RWin to be released before
sending any text containing an "L" keystroke. This prevents such a hotkey from locking the PC. This behavior applies to all sending
modes except SendPlay (which doesn't need it) and blind mode.

Fixed A_LoopFileExt to be blank for any filename having no extension but a period in its pathname. [thanks Yek-Toho-Tua].
Fixed the assignment of integers that are 19 or 20 characters long to work as they did prior to v1.0.48. [thanks Laszlo & Lexikos]
Fixed function definitions to work properly inside a block. [thanks rmarko]

Improved performance of A_Index in expressions by treating it as an integer rather than a string.

Improved performance of if var [not] in/contains. [developed by Lexikos]


Improved ListLines with an option to turn line-logging Off or On. [thanks kenomby & ruespe]
1.0.48 - February 25, 2009

Compatibility: The change most likely to affect backward compatibility is that floating point numbers stored in variables now have
higher precision. Scripts that rely on tiny differences in precision would either need to be reviewed and updated, or have their
compatibility improved by using SetFormat Float (e.g. SetFormat, Float, 0.6) anywhere in the script. SetFormat Float disables
the higher precision, but gives up some of the new, faster floating point performance.

Performance: The main theme of this release is faster performance. Almost all scripts should run faster -- especially those that make
heavy use of expressions and integer math/comparisons (which may run up to three times as fast). To achieve the full benefit, a script
either should avoid using SetFormat or should use SetFormat's fast mode.

Performance improvements

Expressions and function calls are compiled more heavily, making them much faster (especially complex integer expressions, including those with commas).

Binary numbers are cached for variables to avoid conversions to/from strings. This makes numerical operations involving variables
much faster.

Literal integers in expressions and math/comparison commands are replaced with binary integers, which makes them faster; e.g. X+5 and if x > 5.

LOOPs, IFs, and ELSEs that have blocks (braces) are faster due to skipping the opening '{'. A side-effect is that the '{' is omitted from
ListLines.

Thread-creation performance is improved, which should help rapid-fire threads in OnMessage(), RegisterCallback(), and GUI events.
Changes that might affect existing scripts (other than higher-precision floating point described at the top)

When SetFormat, Integer, Hex is in effect, assigning a literal decimal integer to a variable also converts it to hex. Usually this is only a display issue.

For OnMessage() performance, the message number and HWND arrive as standard numbers rather than appearing unconditionally as
hex. Usually this is only a display issue.

To achieve various improvements in performance, scripts now use slightly more memory (proportionate to the number of variables and expressions).

Changed and fixed if var is time and other uses of YYYYMMDDHHMISS date-time stamps to recognize that months outside the
range 1-12 are invalid. [thanks Nick]

Changed and improved dynamic function calling to allow passing more parameters than defined by a function, in which case the
parameters are evaluated but discarded. [developed by Lexikos]

Other improvements

Added function IsFunc(), which indicates whether a function may be called dynamically. [developed by Lexikos]
Added the while-loop, which repeats its commands until its expression evaluates to false. [developed by Lexikos]
Added an assume-static mode for functions. [developed by Lexikos]

Added built-in variables A_IsPaused and A_IsCritical. [developed by Lexikos]

Improved NumPut() to support UInt64 like DllCall(). [thanks Sean]

Improved mouse wheel support by adding WheelLeft and WheelRight as hotkeys and supporting them in Send, Click, and related
commands. However, WheelLeft/Right has no effect on operating systems older than Windows Vista. [developed by Lexikos]

Upgraded compiled script compressor from UPX 3.00 to 3.03.
Fixes

Fixed inability to use MsgBox's timeout parameter when the "Text" parameter had an expression containing commas.

Fixed Menu, Delete, Item-that's-a-submenu not to disrupt the associated submenu. [thanks animeaime & Lexikos]

Fixed the GUI Hotkey control to return usable hotkey names even for dead keys (e.g. "^" instead of Zircumflex). [thanks DerRaphael]


Fixed RegDelete so that it won't delete an entire root key when SubKey is blank. [thanks Icarus]

Fixed registry loops to support subkey names longer than 259 (rare). In prior versions, such subkeys would either be skipped or cause a
crash. [thanks Krzysztof Sliwinski & Eggi]

Fixed FileSelectFolder by providing an option to make it compatible with BartPE/WinPE. [thanks markreflex]

Fixed window/control IDs (HWNDs), which in rare cases wrongly started with 0xFFFFFFFF instead of just 0x. [thanks Micahs]
Fixed inability of Send commands to use the Down/Up modifiers with the "}" character. [thanks neovars]

1.0.47.06 - March 9, 2008

Fixed crash when a function was called concurrently with an optional ByRef parameter omitted by one thread but not omitted by the
other. [thanks DeathByNukes]

Fixed Menu, Tray, MainWindow to enable the menu items in the main window's View menu. [thanks Lexikos]
Added dynamic function calling. [developed by Lexikos]

1.0.47.05 - November 21, 2007

Fixed the Sort command: 1) fixed the "function" option not to misbehave when it's the last option in the list; 2) fixed the "unique" option so that when the delimiter is CRLF, the last item can be detected as a duplicate even when it doesn't end in CRLF; 3) fixed the "unique" option not to append a trailing delimiter when the last item is a duplicate. [thanks Roland]

Fixed RegExMatch() and RegExReplace() to yield correct results even when Haystack and OutputVar are both the same variable. [thanks Superfraggle]

Fixed inability to pass a parameter that is "a variable to which ClipboardAll has been assigned". [thanks Joy2DWorld & Lexikos]
Updated RegEx/PCRE from 7.0 to 7.4. For a summary of the major changes, see www.pcre.org/news.txt. For full details of every change and fix, see www.pcre.org/changelog.txt.

Added GUI control "Tab2" that fixes rare redrawing problems in the original "Tab" control (e.g. activating a GUI window by clicking on a control's scrollbar). The original Tab control is retained for backward compatibility because "Tab2" puts its tab control after its
contained controls in the tab-key navigation order. [thanks Xander]

1.0.47.04 - August 28, 2007

Fixed key-up hotkeys like a up:: not to block the pressing of the "a" key unless the hotkey's #IfWin criteria are met. [thanks Roland]
Fixed Round(Var, NegativeNumber), which in rare cases was off by 1. [thanks Icarus]

Fixed crash of scripts that end in a syntax error consisting of an orphaned IF-statement (broken by 1.0.47.00). [thanks msgbox of the
German forum]

Eliminated the "GetClipboardData" error dialog. Instead, an empty string is retrieved when the data cannot be accessed within the
#ClipboardTimeout period. [thanks ManaUser & Sean]

Changed GUI checkboxes and radio buttons to default to "no word-wrap" when no width, height, or CR/LF characters are specified. This solves display issues under certain unusual DPI settings. [thanks Boskoop]

1.0.47.03 - August 1, 2007

Fixed expressions to allow literal negative hexadecimal numbers that end in "E"; e.g. fn(-0xe). [thanks Laszlo]
Fixed block syntax to allow a function-call immediately to the right of a '}'. [thanks Roland]

1.0.47.02 - July 19, 2007

Fixed the Number option of Edit controls to properly display a balloon tip when the user types something other than a digit. [thanks
tfcahm]

Fixed WM_TIMER not to be blocked unless it's posted to the script's main window. [thanks tfcahm]

Fixed wildcard hotkeys not to acquire tilde behavior when the same hotkey exists in the script with a tilde. [thanks Lexikos]

Fixed declaration initializers not to retain whitespace at the end of literal numbers. Also, they now allow spaces between a closing quote


and the next comma. [thanks Hardeep]
1.0.47.01 - July 8, 2007

Fixed RunAs not to crash or misbehave when a domain is specified. [thanks Markus Frohnmaier]

Changed relational operators to yield integers even when the inputs are floating point; e.g. 1.0 < 2.0 yields 1 vs. 1.0. [thanks Lexikos] 1.0.47 - June 19, 2007

Added support for function libraries, which allow a script to call a function in an external file without having to use #Include.
Added RegisterCallback(), which creates a machine-code address that when called, redirects the call to a function in the script.
[developed by Jonathan Rennison (JGR)]

Added NumGet() and NumPut(), which retrieve/store binary numbers with much greater speed than Extract/InsertInteger.
Improved Sort with an option to do custom sorting according to the criteria in a callback function. [thanks Laszlo]

Improved OnMessage() with an option to allow more than one simultaneous thread. [thanks JGR]

Improved Critical with an option to change the message-check interval, which may improve reliability for some usages. [thanks
Majkinetor and JGR]

Changed Critical to put SetBatchLines -1 into effect.

Changed the error messages produced by #ErrorStdOut to contain a space before the colon. [thanks Toralf]

Fixed OnMessage() functions that return one of their own local variables to return the number in that variable, not 0.

Fixed potential crashing of built-in variables that access the registry (e.g. A_AppData, A_Desktop, A_MyDocuments, A_ProgramFiles). [thanks Tekl]

1.0.46.17 - May 31, 2007

Fixed A_UserName (broken by 1.0.46.16).
1.0.46.16 - May 30, 2007

Fixed Gui, Tab, TabName when used after a previous Gui Tab. [thanks Toralf]

Improved SetTimer to treat negative periods as "run only once". [thanks Majkinetor]

Added GuiControlGet Hwnd, which is a more modular/dynamic way to retrieve a control's HWND. [thanks Majkinetor]

Added built-in variables A_ThisLabel and A_ThisFunc, which contain the names of the currently-executing label/function. [thanks Titan & Majkinetor]

1.0.46.15 - May 9, 2007

Fixed GuiControl, GuiControlGet, and Gui ListView/TreeView to support static variables and ByRefs that point to globals/statics.
[thanks Peter]

Fixed FileInstall causing the Random command to become non-random in compiled scripts. [thanks Velocity]

Reduced the size of compiled scripts by about 16 KB due to UPX 3.0. [thanks to atnbueno for discovering the optimal command-line
switches]

1.0.46.14 - May 2, 2007

Added the "require administrator" flag to the installer to avoid a warning dialog on Windows Vista. [thanks Roussi Nikolov]
1.0.46.13 - May 1, 2007

Fixed hotkeys like *x to fire even when x is also a hotkey that is prevented from firing due to #IfWin. [thanks Joy2DWorld &
Engunneer]

Improved optional parameters to accept quoted/literal strings as default values.


Improved ByRef parameters with the ability to be optional (i.e. they may accept default values). [thanks Corrupt]
1.0.46.12 - April 24, 2007

Fixed inability to recognize a literal scientific notation number that begins with 0, such as 0.15e+1. [thanks Laszlo]
1.0.46.11 - April 23, 2007

Fixed inability to have a function-call as the first item in certain comma-separated expressions. [thanks Majkinetor]

Fixed WinTitles like ahk_id %ControlHwnd% in ControlGet's FindString/Choice/List, and Control's Add/Delete/Choose. [thanks
Freighter & PhiLho]

Improved floating point support to recognize scientific notation; e.g. 1.2e-5 (the decimal point is mandatory). Also improved "SetFormat Float" with an option to output in scientific notation. [thanks Laszlo]

1.0.46.10 - March 22, 2007

Fixed StringSplit inside assume-local functions so that it creates a local array even when OutputArray0 exists as a global but not a local. [thanks KZ]

Improved ListView's item-changed notification ("I") to indicate via ErrorLevel whether the item has been selected/deselected,
focused/unfocused, and/or checked/unchecked. [thanks foom]

Added an additional layer of protection to compiled scripts. It is recommended that scripts containing sensitive data or source code be
recompiled with the /NoDecompile switch.

1.0.46.09 - March 4, 2007

Fixed := deep inside expressions when used to assign the result of a recursive function to a local variable (broken by 1.0.46.06). [thanks Laszlo]

Fixed inability to pass certain ternary expressions to ByRef parameters. [thanks Titan]

Fixed GuiControlGet, OutputVar, Pos so that it doesn't make the OutputVar blank. [thanks PhiLho]

Changed and fixed continuation sections so that the "Comment" option doesn't force the LTrim option into effect. [thanks Titan]
Changed the Terminal Server Awareness flag back to "disabled" on AutoHotkey.exe and compiled scripts. This improves flexibility and backward compatibility (see discussion at forum).

1.0.46.08 - February 7, 2007

Fixed unreliability of ComSpec and environment variables on Windows 9x (broken by v1.0.46.07). [thanks Loriss]

Changed: When AutoHotkey.exe is launched without a script specified, it will now run (or prompt you to create) the file
AutoHotkey.ahk in the My Documents folder. The only exception is when AutoHotkey.ini exists in the working directory, in which case it uses the old behavior of executing that file.

Improved DllCall to support an integer in place of the function name, which is interpreted as the address of the function to call. [thanks Sean]

1.0.46.07 - January 23, 2007

Fixed crash of illegally-named dynamic variables on the left of an equal-sign assignment (broken by v1.0.45). [thanks PhiLho]

Fixed FileMoveDir's "Option 2" to work properly even when the directory is being both renamed and moved. [thanks bugmenot]

Fixed inability to pass a variable ByRef if that same expression changed it from empty to non-empty (when #NoEnv is absent). [thanks
Joy2DWorld]

Changed DllCall's A_LastError to reflect only changes made by the script, not by AutoHotkey itself. [thanks Azerty]
1.0.46.06 - January 16, 2007

Applied minor fixes and improvements to regular expressions by upgrading from PCRE 6.7 to 7.0. One of the most notable
improvements is the `a option, which recognizes any type of newline (namely `r, `n, or `r`n). Similarly, the \R escape sequence means


"any single newline of any type". See also: Full PCRE changelog

Changed and fixed all Control commands and StatusBarWait to obey SetTitleMatchMode RegEx as documented.
Changed RegExReplace() to return the original/unaltered string rather than "" when an error occurs.

Changed: Enabled the Terminal Server Awareness flag on AutoHotkey.exe and compiled scripts.

Improved performance when assigning large strings returned from user-defined functions. [thanks Laszlo]
1.0.46.05 - January 4, 2007

Fixed the Input command to allow named end keys like {F9} to work even when the shift key is being held down (broken by v1.0.45). [thanks Halweg]

Fixed inability of "Gui Show" to focus the GUI window when the tray menu is used both to reload the script and to show the GUI
window. [thanks Rnon]

Fixed inability to pass some types of assignments (:=) to a ByRef parameter. [thanks Laszlo]
1.0.46.04 - January 2, 2007

Fixed inability to pass the result of an assignment (:=) to a ByRef parameter. [thanks Titan]
1.0.46.03 - December 18, 2006

Fixed ListView's floating point sorting to produce the correct ordering. [thanks oldbrother/Goyyah/Laszlo]
1.0.46.02 - December 17, 2006

Fixed environment variables to work properly as input variables in various commands such as StringLen and StringReplace (broken by 1.0.44.14). [thanks Camarade_Tux]

1.0.46.01 - December 15, 2006

NOTE: Although this release has been extensively tested, several low-level enhancements were made. If you have any mission-critical scripts, it is recommended that you retest them and/or wait a few weeks for any bugs to get fixed.

Fixed comma-separated declaration initializers such as local x = 1, y = 2 to work even when immediately below an if/else/loop
statement.

Fixed comma-separated expressions so when the leftmost item is an assignment, it will occur before the others rather than after. [thanks Laszlo]

Changed and fixed function-calls so that any changes they make to dynamic variable names, environment variables, and built-in
variables (such as Clipboard) are always visible to subsequent parts of the expression that called them.

Changed: When a multi-statement comma is followed immediately by a variable and an equal sign, that equal sign is automatically
treated as a := assignment. For example, all of the following are assignments: x:=1, y=2, a=b=c.

Changed comma-separated expressions to produce the following effects: 1) the leftmost /= operator becomes true divide rather than
EnvDiv; 2) blank values are not treated as zero in math expressions (thus they yield blank results).

Improved the performance of expressions by 5 to 20% (depending on type).

Improved the new assignment operators such as .= to support the Clipboard variable (even in comma-separated expressions).
Improved the .= operator so that it doesn't require a space to its left.

Improved GUI controls to accept static variables as their associated variables (formerly only globals were allowed).

Added option HwndOutputVar to Gui Add, which stores a control's HWND in OutputVar. [thanks Corrupt & Toralf]
1.0.46 - November 29, 2006

NOTE: Although this release has been extensively tested and is not expected to break any existing scripts, several low-level
enhancements were made. If you have any mission-critical scripts, it is recommended that you retest them and/or wait a few weeks for any bugs to get fixed.


Added function SubStr(), which retrieves the specified number of characters at the specified position in a string.

Added assignment operators //=, .=, |=, &=, ^=, >>=, and <<=, which can be used anywhere in expressions. For example, Var .= "abc" appends the string "abc" to Var's current contents.

Added full support in expressions for the operators :=, ++, --, +=, -=, *=, and /= (formerly, they could be used only as the leftmost
operator on a line). All assignment operators (especially ++ and --) behave in a C-like way when their result is used by some other
operator.

Added the ternary operator (?:), which is a shorthand replacement for the if-else statement. For example, var := x>y ? 2 : 3 assigns
the value 2 if x is greater than y; otherwise it assigns 3.

Added support for comma-separated expressions, which allow a single line to contain multiple assignments, function calls, and other
expressions. [thanks PhiLho & Titan]

Improved variable declarations to support initialization on the same line. Note: A static variable's initialization occurs only once, before the script begins executing.

Improved line continuation to support all expression operators. For example, a line that starts with "?" or "+" is automatically appended
to the line above it.

Improved performance of operators "." and ".=" to be as fast as the percent-sign method of appending a string.

Improved expressions to allow more types of consecutive unary operators such as !!Var. [thanks Laszlo]

Changed Critical to check messages less often (20 vs. 10ms), which improves the reliability of frequently-called OnMessage functions.
[thanks Majkinetor]

Changed: A variable named simply "?" is no longer valid in expressions due to the new ternary operator.

Fixed hotkeys to support ::: (colon as a hotkey) and : & x (colon as a hotkey prefix).

Fixed the installer to remove psapi.dll from the AutoHotkey folder (except on Windows NT4). This avoids a conflict with Internet
Explorer 7. [thanks to all who reported it]

1.0.45.04 - November 15, 2006

Fixed crash on Windows 9x when a script doesn't actually run (e.g. due to syntax error) (broken by v1.0.45). [thanks rogerg]

Changed Control Style|ExStyle to report ErrorLevel 0 vs. 1 when the requested style change wasn't necessary because it was already in effect.

Improved #Include to support %A_AppData% and %A_AppDataCommon%. [thanks Tekl]
1.0.45.03 - November 12, 2006

Fixed file-pattern loops not to crash when recursing into paths longer than 259 characters. In addition, such paths and files are now
ignored (skipped over) by file-pattern loops, FileSetAttrib, and FileSetTime. [thanks PhilR]

Fixed functions that call themselves and assign the result to one of their own locals (broken by v1.0.45). [thanks bjennings]

Fixed crash of scripts containing regular expressions that have compile errors. [thanks PhiLho]

Fixed GuiControl not to convert checkboxes into 3-state unless requested. [thanks JBensimon]

Changed UrlDownloadToFile to announce a user-agent of "AutoHotkey" to the server rather than a blank string. [thanks jaco0646]
Improved continuation sections to support semicolon comments inside the section via the option-word Comments.

1.0.45.02 - November 8, 2006

Fixed StringUpper and StringLower to work when OutputVar is the clipboard (broken by v1.0.45). [thanks songsoverruins]

Fixed the hotkeys ~Alt, ~Control, and ~Shift to fire upon press-down rather than release (broken by v1.0.44).

Background: Without the tilde, Alt/Control/Shift fire upon release to avoid taking over both the left and right key. But a specific left/right hotkey like LAlt or RShift fires upon press-down.

1.0.45.01 - November 7, 2006

Fixed FileReadLine and FileSelectFile not to crash or misbehave when other threads interrupt them (broken by v1.0.45). [thanks toralf]


Fixed RegExMatch() so that when there's no match, named subpatterns are properly set to "" in the output array. [thanks PhiLho]
Fixed RegExMatch()'s "J" option to properly write duplicate named subpatterns to the output array. [thanks PhiLho]

Changed SetWorkingDir and #Include DirName to succeed even for a root directory such as C: that lacks a backslash.

Improved DllCall() to display a warning dialog if the called function writes to a variable of zero capacity.

1.0.45 - November 4, 2006

NOTE: Although this release has been extensively tested and is not expected to break any existing scripts, several low-level performance enhancements were made. If you have any mission-critical scripts, it is recommended that you retest them and/or wait a few weeks for
any bugs to get fixed.

Added support for regular expressions via RegExMatch(), RegExReplace(), and SetTitleMatchMode RegEx. [thanks Philip Hazel &
PhiLho]

Improved performance and memory utilization of StringReplace.

Improved performance of the := operator for expressions and functions involving long strings.

Improved ControlClick with a new option "NA" that avoids activating the target window (this mode also improves reliability in some
cases). In addition, it's been documented that SetControlDelay -1 can improve the reliability of ControlClick in some cases. [thanks
nnesori]

Changed GUI buttons to default to "no word-wrap" when no width, height, or CR/LF characters were specified. This may solve button
display issues under some desktop themes.

Fixed "Transform HTML" for the following characters: &`n><

Fixed misinterpretation of lines starting with "if not is" such as "if not IsDone".

Fixed inability of "Gui Show" to move a window vertically downward to where its bottommost row of pixels is now.

Fixed inability to use GroupActivate as the only line beneath an IF or ELSE.

Fixed inability of the Input command to differentiate between end-keys enclosed in braces and their (un)shifted counterparts; e.g. '{' vs.
'['. [thanks Laszlo]

Older Changes

Visit www.autohotkey.com/changelog/ for even older changes.


Script Compatibility

Although many scripts written for AutoHotkey 1.0 do not require changes to run on AutoHotkey 1.1, some may function incorrectly due to necessary differences between the two versions. As the most problematic differences only affect advanced functionality like DllCall, most users do not need to be concerned.

AutoHotkey 1.1 is also known as "AutoHotkey_L", while AutoHotkey 1.0 was retrospectively labelled "AutoHotkey Basic". Some older versions of AutoHotkey_L used 1.0.* version numbers, so for clarity, this document refers to the two branches of AutoHotkey by name rather than version number.

Note: Some of the most common problems are caused by changes required to support Unicode text, and can be avoided by simply using the ANSI version of AutoHotkey_L.

Table of Contents

Basic

High impact:

Certain syntax errors are no longer tolerated

FileRead may return corrupt binary data

Variable and function names do not allow [, ] or ?
DPI scaling is enabled by default for GUIs

Medium impact:

Transform's Unicode sub-command is unavailable on Unicode versions

AutoHotkey.ahk is launched instead of AutoHotkey.ini
SetFormat, Integer, H is case-sensitive

A_LastError is modified by more commands

MsgBox's handles commas more consistently

Gui +Owner overrides additional styles

SoundSet and SoundGet work better on Vista and later

~Tilde affects how custom modifier keys work

x & y:: causes both x:: and x up:: to fire when x is released

Low impact:

If var is type ignores the system locale by default

GroupActivate sets ErrorLevel and GroupAdd's Label works differently
Run and RunWait interpret Target differently

Control-Z is not interpreted as end-of-file

Compatibility mode may cause confusion

A_IsCompiled is always read-only

Leading and trailing `t sequences are no longer discarded

Advanced

Unicode vs ANSI
VarSetCapacity

DllCall

NumPut / NumGet

Pointer Size

Basic

Syntax Errors

Certain syntax errors which were tolerated by AutoHotkey Basic are not tolerated by AutoHotkey_L. Most such errors can be easily
corrected once they are identified. The following errors are detected immediately upon launching a script in AutoHotkey_L, and must be corrected for the script to run:

A space, tab or comma is required between each command and its parameters. For example, MsgBox< foo and If!foo are not
tolerated.

Hotkey, IfSomething, where Something is invalid, is not tolerated.

Some other syntax errors are detected while the script is running. These cause an error message to be displayed prior to exiting the
current thread:


Common: Unrecognized or badly formatted Gui, Gui Show or GuiControl options.

GroupAdd with a blank group name. Previously this caused the thread to silently exit.

Gui option +LastFoundExist must not be combined with another option, since that would cause it to act the same as +LastFound.

Some other syntax errors are currently not detected, but cause problems with AutoHotkey_L:
Auto-concat with ( is more selective, so some invalid expressions like 12(34) no longer work.

FileRead

FileRead translates text between code pages in certain common cases and therefore might output corrupt binary data. To avoid this, add the *c option or use FileOpen instead.

Variable and Function Names

The characters [, ] and ? are reserved for use in expressions, so are no longer valid in variable names. Consequently, ? (used in ternary operations) no longer requires a space on either side. See also object syntax.

Errors may or may not be detected automatically:

If a script used these characters in variable names in expressions, generally the script will run without displaying an error message,

but will misbehave as the characters will be interpreted as operators rather than as part of a variable name.

If these characters are used in a double-deref (such as Array%n% where n contains one of the above characters), an error message is
displayed when the double-deref is evaluated, while the script is running.

If these characters are used in other contexts, such as on the left hand side of an assignment, in the name of a command's
input/output variable or between %percent% signs, an error message is displayed and the script is prevented from launching.

DPI Scaling

DPI scaling is enabled by default for script GUIs to ensure they scale according to the system DPI setting. If enabled and the system DPI setting is not 96 (100%), positions and sizes accepted by or returned from Gui commands are not compatible with other commands. To
disable DPI scaling, use Gui -DPIScale.

Transform

Some Transform sub-commands are altered or unavailable in Unicode versions of AutoHotkey_L:

Transform, Unicode is unavailable. To assign Unicode text to the clipboard, use a regular assignment. See also: StrPut/StrGet.

Transform, HTML supports additional features.
Default Script

When AutoHotkey_L is launched without specifying a script, an .ahk file is loaded by default instead of an .ini file. The name of this file depends on the filename of the current executable. For more details, see Passing Command Line Parameters to a Script.

SetFormat, Integer[Fast], H

When an uppercase H is used, hexadecimal digits A-F will also be in uppercase. AutoHotkey Basic always uses lowercase digits. See
SetFormat.

A_LastError

The following commands now set A_LastError to assist with debugging: FileAppend, FileRead, FileReadLine, FileDelete, FileCopy,
FileMove, FileGetAttrib/Time/Size/Version, FileSetAttrib/Time, FileCreateDir, RegRead, RegWrite, RegDelete. Using any of these
commands causes the previous value of A_LastError to be overwritten.

MsgBox

MsgBox's smart comma handling has been changed to improve flexibility and consistency with all other commands. In most cases,
MsgBox will just work as intended. In some rare cases, scripts relying on the old quirky behaviour may observe a change in behaviour. For instance:

; This is now interpreted as an expression (Options) followed by text (Title)
; instead of as a single expression (Text) with multiple sub-expressions:
MsgBox % x, y

; Parentheses can be added to force the old interpretation:

MsgBox % (x, y)

; This now shows an empty dialog instead of the text "0, Title":
MsgBox 0, Title

; These behave as expected in both AutoHotkey_L and AutoHotkey Basic:


MsgBox 0, Title, % ""   ; Shows an empty dialog
MsgBox 0`, Title        ; Shows the text "0, Title"

; This now shows an empty dialog instead of the text ", Title":
MsgBox,, Title

Gui +Owner

Applying the +Owner option to a Gui also removes the WS_CHILD style and sets the WS_POPUP style. This may break scripts which used +Owner to set the parent window of a Gui after setting the styles.

Sound Commands on Windows Vista and later

SoundSet, SoundGet, SoundSetWaveVolume and SoundGetWaveVolume have improved support for Windows Vista and later. Typical changes in behaviour include:

Scripts affecting the whole system (as is usually intended) instead of just the script itself.
Devices being numbered differently - each output or input is considered a separate device.

~Tilde and Custom Combination Hotkeys

As of [v1.1.14], the tilde prefix affects how a key works when used as a modifier key in a custom combination.
Custom Combinations and Down/Up Hotkeys

Except when the tilde prefix is used, if both a key-down and a key-up hotkey are defined for a custom modifier key, they will both fire
when the key is released. For example, x & y:: causes both x:: and x up:: to fire when x is released, where previously x:: never fired.

If var is type

If var is type ignores the system locale unless StringCaseSense, Locale has been used.
Window Groups

GroupActivate sets ErrorLevel to 1 if no window was found to activate or 0 otherwise. Previously, ErrorLevel was left unchanged.
GroupAdd's Label parameter applies to the window group as a whole instead of to one particular window specification within the group. A discussion of this change can be found on the forums. However, using this parameter is not recommended; check ErrorLevel after
calling GroupActivate instead.

Run / RunWait

AutoHotkey_L includes some enhancements to the way the Run and RunWait commands interpret the Target parameter. This allows
some things that didn't work previously, but in some very rare cases, may also affect scripts which were already working in AutoHotkey Basic. The new behaviour is as follows:

If Target begins with a quotation mark, everything up to the next quotation mark is considered the action, typically an executable
file.

Otherwise the first substring which ends at a space and is either an existing file or ends in .exe, .bat, .com, .cmd or .hta is
considered the action. This allows file types such as .ahk, .vbs or .lnk to accept parameters while still allowing "known"
executables such as wordpad.exe to be launched without an absolute path as in previous versions.

Control-Z

Loop Read and FileReadLine no longer interpret the character Control+Z (0x1A) as an end-of-file marker. Any Control+Z, even one
appearing at the very end of the file, is loaded as-is. FileRead already ignored this character, so is not affected by this issue.

Compatibility Mode

If Compatibility mode is set to Windows 95, 98/ME or NT4 in the properties of the EXE file used to run the script, the script may not
behave correctly. This is because compatibility mode causes a specific version of Windows to be reported to the application, but
AutoHotkey_L omits support for these versions. For example, setting compatibility mode to Windows 95 or 98/ME will cause MsgBox
%A_OSVersion% to report WIN_NT4.

A_IsCompiled

A_IsCompiled is defined as an empty string if the script has not been compiled. Previously it was left undefined, which meant that
assignments such as A_IsCompiled := 1 were valid if the script hadn't been compiled. Now it is treated as a read-only built-in variable in all cases.


Escaped Whitespace

Escaped whitespace characters such as `t and ` are no longer trimmed from the beginning and end of each arg. For example,
StringReplace s, s, `t is now valid and will remove all tab characters from s.

Unicode vs ANSI

A text value is often referred to as a string, as each text value is stored as a sequence or string of characters. The numeric character code and size (in bytes) of each character depends on which version of AutoHotkey you are using: Unicode or ANSI. These details are
typically important for scripts which do any of the following:

Pass strings to external functions via DllCall.

Pass strings via PostMessage/SendMessage.

Manipulate strings directly via NumPut/NumGet.

Use VarSetCapacity to ensure a variable can hold a specific number of characters.

Scripts designed with one particular format in mind will often encounter problems when run on the wrong version of AutoHotkey. For
instance, some scripts written for AutoHotkey Basic will function correctly on the ANSI version of AutoHotkey_L but fail on Unicode
versions. If you aren't sure which version you are using, run the following script:

MsgBox % A_IsUnicode ? "Unicode" : "ANSI"

ANSI: Each character is one byte (8 bits). Character codes above 127 depend on your system's language settings.

Unicode: Each character is two bytes (16 bits). Character codes are as defined by the UTF-16 format.

Semantic note: Technically, some Unicode characters are represented by two 16-bit code units, collectively known as a "surrogate pair." Similarly, some ANSI code pages (commonly known as Double Byte Character Sets) contain some double-byte characters. However, for practical reasons these are almost always treated as two individual units (referred to as "characters" for simplicity).

VarSetCapacity

VarSetCapacity sets the capacity of a var in bytes. To set a variable's capacity based on the number of characters, the size of a character must be taken into account. For example:

VarSetCapacity(ansi_var,    capacity_in_chars)
VarSetCapacity(unicode_var, capacity_in_chars * 2)
VarSetCapacity(native_var,  capacity_in_chars * (A_IsUnicode ? 2 : 1))
VarSetCapacity(native_var,  t_size(capacity_in_chars))  ; see below

There are two main uses for VarSetCapacity:

1. Expand a variable to hold an estimated number of characters, to enhance performance when building a string by means of gradual

concatenation. For example, VarSetCapacity(var, 1000) allows for 1000 bytes, which is only 500 characters on Unicode
versions of AutoHotkey_L. This could affect performance, but the script should still function correctly.

2. Resize a variable to hold a binary structure. If the structure directly contains text, the format of that text must be taken into
account. This depends on the structure - sometimes ANSI text will be used even in a Unicode version of AutoHotkey_L. If the

variable is too small, the script may crash or otherwise behave unpredictably (depending on how the structure is used).
DllCall

When the "Str" type is used, it means a string in the native format of the current build. Since some functions may require or return
strings in a particular format, the following string types are available:

 Char Size                         C / Win32 Types                                                                    Encoding
WStr16-bitwchar_t*, WCHAR*, LPWSTR, LPCWSTRUTF-16

AStr8-bitchar*, CHAR*, LPSTR, LPCSTR                   ANSI (the system default ANSI code page)

Str          --        TCHAR*, LPTSTR, LPCTSTR                       Equivalent to WStr in Unicode builds and AStr in ANSI builds.

If "Str" or the equivalent type for the current build is used as a parameter, the address of the string or var is passed to the function,
otherwise a temporary copy of the string is created in the desired format and passed instead. As a general rule, "AStr" and "WStr" should not be used if the function writes a value into that parameter.

Note: "AStr" and "WStr" are equally valid for parameters and the function's return value.

In general, if a script calls a function via DllCall which accepts a string as a parameter, one of the following approaches must be taken:

1. If both Unicode (W) and ANSI (A) versions of the function are available, call the appropriate one for the current build. In the
following example, "DeleteFile" is internally known as "DeleteFileA" or "DeleteFileW". Since "DeleteFile" itself doesn't really

exist, DllCall automatically tries "A" or "W" as appropriate for the current build:


DllCall("DeleteFile", "Ptr", &filename)
DllCall("DeleteFile", "Str", filename)

In this example, &filename passes the address of the string exactly as-is, so the function must expect a string in the same format as
the "Str" type. Note that "UInt" must be used in place of "Ptr" in AutoHotkey Basic, but the resulting code may not be 64-bit
compatible.

Note: If the function cannot be found exactly as specified, AutoHotkey_L appends the "A" or "W" suffix regardless of which DLL
is specified. However, AutoHotkey Basic appends the "A" suffix only for functions in User32.dll, Kernel32.dll, ComCtl32.dll, or
Gdi32.dll.

2. If the function only accepts a specific type of string as input, the script may use the appropriate string type:

DllCall("DeleteFileA", "AStr", filename)
DllCall("DeleteFileW", "WStr", filename)

3. If the function must modify a string (in a non-native format), the script must allocate a buffer as described above and pass its
address to the function. If the parameter accepts input, the script must also convert the input string to the appropriate format; this

can be done using StrPut.
NumPut / NumGet

When NumPut or NumGet are used with strings, the offset and type must be correct for the given type of string. The following may be
used as a guide:

;  8-bit/ANSI   strings:  size_of_char=1  type_of_char="Char"

; 16-bit/UTF-16 strings:  size_of_char=2  type_of_char="UShort"
nth_char := NumGet(var, (n-1)*size_of_char, type_of_char)
NumPut(nth_char, var, (n-1)*size_of_char, type_of_char)

If var contains a string in the native format, the appropriate values may be determined based on the value of A_IsUnicode:

nth_char := NumGet(var, t_size(n-1), t_char())
NumPut(nth_char, var, t_size(n-1), t_char())

; Define functions for convenience and clarity:
t_char() {

    return A_IsUnicode ? "UShort" : "Char"

}

t_size(char_count=1) {

    return A_IsUnicode ? char_count*2 : char_count

}

Pointer Size

Pointers are 4 bytes in 32-bit builds (including AutoHotkey Basic) and 8 bytes in 64-bit builds. Scripts using structures or DllCalls may need to account for this to run correctly on both platforms. Specific areas which are affected include:

Offset calculation for fields in structures which contain one or more pointers.
Size calculation for structures containing one or more pointers.

Type names used with DllCall, NumPut or NumGet.

For size and offset calculations, use A_PtrSize. For DllCall, NumPut and NumGet, use the Ptr type where appropriate.

Remember that the offset of a field is usually the total size of all fields preceding it. Also note that handles (including types like HWND and HBITMAP) are essentially pointer-types.

/*

  typedef struct _PROCESS_INFORMATION {

    HANDLE hProcess;    // Ptr

    HANDLE hThread;

    DWORD  dwProcessId; // UInt (4 bytes)

    DWORD  dwThreadId;

  } PROCESS_INFORMATION, *LPPROCESS_INFORMATION;

*/

VarSetCapacity(pi, A_PtrSize*2 + 8) ; Ptr + Ptr + UInt + UInt
DllCall("CreateProcess", <omitted for brevity>, "Ptr", &pi, <omitted>)
hProcess    := NumGet(pi, 0)         ; Defaults to "Ptr".

hThread     := NumGet(pi, A_PtrSize) ;

dwProcessId := NumGet(pi, A_PtrSize*2,     "UInt")

dwProcessId := NumGet(pi, A_PtrSize*2 + 4, "UInt")



 

Concepts and Conventions

This document covers some general concepts and conventions used by AutoHotkey, with focus on explanation rather than code. The
reader is not assumed to have any prior knowledge of scripting or programming, but should be prepared to learn new terminology.

For more specific details about syntax, see Scripting Language.
Table of Contents

Values

Strings
Numbers
Boolean
Nothing
Objects

Object Protocol

Variables

Uninitialised Variables

Built-in Variables
Environment Variables
Caching

Functions/Commands
Control Flow

Details

String Encoding

Pure Numbers

Names

Variable References vs Values
References to Objects

Values

A value is simply a piece of information within a program. For example, the name of a key to send or a program to run, the number of
times a hotkey has been pressed, the title of a window to activate, or whatever else has some meaning within the program or script.

AutoHotkey supports these types of values:
Strings (text)

Numbers (integers and floating-point numbers)
Objects

Some other related concepts:
Boolean

Nothing
Strings

A string is simply text. Each string is actually a sequence or string of characters, but can be treated as a single entity. The length of a
string is the number of characters in the sequence, while the position of a character in the string is merely that character's sequential
number. By convention in AutoHotkey, the first character is at position 1.

A string of digits (or any other supported number format) is automatically interpreted as a number when a math operation or comparison requires it.

How literal text should be written within the script depends on the context. For details, see Legacy Syntax and Strings (in expressions). For a more detailed explanation of how strings work, see String Encoding.

Numbers

AutoHotkey supports these number formats:
Decimal integers, such as 123, 00123 or -1.

Hexadecimal integers, such as 0x7B, 0x007B or -0x1.
Decimal floating-point numbers, such as 3.14159.

Hexadecimal numbers must use the 0x or 0X prefix, except where noted in the documentation. This prefix must be written after the + or -


sign, if present, and before any leading zeroes. For example, 0x001 is valid, but 000x1 is not.

Numbers written with a decimal point are always considered to be floating-point, even if the fractional part is zero. For example, 42 and 42.0 are usually interchangeable, but not always. Scientific notation is also recognized, but only if a decimal point is present (e.g. 1.0e4 and -2.1E-4).

The decimal separator is always a dot, even if the user's regional settings specify a comma.

When a number is converted to a string, it is formatted according to the current integer or float format. Although the SetFormat command can be used to change the current format, it is usually better to use the Format function to format a string. Floating-point numbers can

also be formatted by using the Round function.

For details about the range and accuracy of numeric values, see Pure Numbers.
Boolean

A boolean value can be either true or false. Boolean values are used to represent anything that has exactly two possible states, such as the truth of an expression. For example, the expression (x <= y) is true when x has lesser or equal value to y. A boolean value could also
represent yes or no, on or off, down or up (such as for GetKeyState) and so on.

AutoHotkey does not have a specific boolean type, so it uses the integer value 0 to represent false and 1 to represent true. When a value is required to be either true or false, a blank or zero value is considered false and all other values are considered true. (Objects are always considered true.)

The words true and false are built-in variables containing 1 and 0. They can be used to make a script more readable.
Nothing

AutoHotkey does not have a value which uniquely represents nothing, null, nil or undefined, as seen in other languages. Instead, an
empty string (a string of zero length) often has this meaning.

If a variable or parameter is said to be "empty" or "blank", that usually means an empty string (a string of zero length).
Objects

There are generally two ways of viewing objects:

An object contains a group of values, allowing the group itself to be treated as one value. For example, an object could contain an

array or sequence of items, or a set of related values, such as the X and Y coordinates of a position on the screen. Objects can be
used to build complex structures by combining them with other objects.

An object can represent a thing, a service, or something else, and can provide ways for the script to interact with this thing or
service. For example, a BankAccount object might have properties such as the account number, current balance and the owner of
the account, and methods to withdraw or deposit an amount.

The proper use of objects (and in particular, classes) can result in code which is modular and reusable. Modular code is usually easier to test, understand and maintain. For instance, one can improve or modify one section of code without having to know the details of other
sections, and without having to make corresponding changes to those sections. Reusable code saves time, by avoiding the need to write
and test code for the same or similar tasks over and over.

When you assign an object to a variable, as in myObj := {}, what you store is not the object itself, but a reference to the object. Copying that variable, as in yourObj := myObj, creates a new reference to the same object. A change such as myObj.ans := 42 would be
reflected by both myObj.ans and yourObj.ans, since they both refer to the same object. However, myObj := Object() only affects the variable myObj, not the variable yourObj, which still refers to the original object.

Object Protocol

This section builds on these concepts which are covered in later sections: variables, functions

Objects work through the principle of message passing. You don't know where an object's code or variables actually reside, so you must pass a message to the object, like "give me foo" or "go do bar", and rely on the object to respond to the message. Objects in AutoHotkey support the following basic messages:

Get a value.

Set a value, denoted by :=.
Call a method, denoted by ().

Each message can optionally have one or more parameters (and, for Set, the value). Usually there is at least one parameter, and it is
interpreted as the name of a property or method, a key or an array index, depending on the object and how you're using it. The
parameters of a message are specified using three different patterns: .Name, [Parameters] and (Parameters), where Name is a literal
name or identifier, and Parameters is a list of parameters (as sub-expressions), which can be empty/blank ([] or ()).


For Get and Set, .Name and [Parameters] can be used interchangeably, or in combination:

myObj[arg1, arg2, ..., argN]
myObj.name

myObj.name[arg2, ..., argN]

For Call, .Name and [Parameter] can be used interchangeably, and must always be followed by (Parameters):

myObj.name(arg2, ..., argN)
myObj[arg1](arg2, ..., argN)

Notice that if name is present, it becomes the first parameter. myObj.name is equivalent to myObj["name"], while myObj.123 is
equivalent to myObj[123]. This is true for every type of object, so it is always possible to compute the name of a property or method at
runtime, rather than hard-coding it into the script.

Although name or arg1 is considered to be the first parameter, remember that these are just messages, and the object is free to handle
them in any way. In a method call such as those shown above, usually the object uses name or arg1 to identify which method should be called, and then only arg2 and beyond are passed to the method. In effect, arg2 becomes the method's first apparent parameter.

Generally, Set has the same meaning as an assignment, so it uses the same operator:

myObj[arg1, arg2, ..., argN] := value
myObj.name := value

myObj.name[arg2, ..., argN] := value

Currently there is also a "hybrid" syntax allowed with Set, but it is best not to use it:

myObj.name(arg2, ..., argN) := value

Technically, value is passed as the last the parameter of the Set message; however, this detail is almost never relevant to script authors. Generally one can simply think of it as "the value being assigned".

Variables

A variable allows you to use a name as a placeholder for a value. Which value that is could change repeatedly during the time your script is running. For example, a hotkey could use a variable press_count to count the number of times it is pressed, and send a different key whenever press_count is a multiple of 3 (every third press). Even a variable which is only assigned a value once can be useful. For
example, a WebBrowserTitle variable could be used to make your code easier to update when and if you were to change your preferred web browser, or if the title or window class changes due to a software update.

In AutoHotkey, variables are created simply by using them. Each variable is not permanently restricted to a single data type, but can
instead hold a value of any type: string, number or object. Each variable starts off empty/blank; in other words, each newly created
variable contains an empty string until it is assigned some other value.

A variable has three main aspects:
The variable's name.

The variable itself.
The variable's value.

Certain restrictions apply to variable names - see Names for details. In short, it is safest to stick to names consisting of ASCII letters
(which are case insensitive), digits and underscore, and to avoid using names that start with a digit.

A variable name has scope, which defines where in the code that name can be used to refer to that particular variable; in other words,
where the variable is visible. If a variable is not visible within a given scope, the same name can refer to a different variable. Both
variables might exist at the same time, but only one is visible to each part of the script. Global variables are visible in the "global scope" (that is, outside of functions), but must usually be declared to make them visible inside a function. Local variables are visible only inside the function which created them.

A variable can be thought of as a container or storage location for a value, so you'll often find the documentation refers to a variable's
value as the contents of the variable. For a variable x := 42, we can also say that the variable x has the number 42 as its value, or that
the value of x is 42.

It is important to note that a variable and its value are not the same thing. For instance, we might say "myArray is an array", but what we really mean is that myArray is a variable containing a reference to an array. We're taking a shortcut by using the name of the variable to refer to its value, but "myArray" is really just the name of the variable; the array object doesn't know that it has a name, and could be

referred to by many different variables (and therefore many names).
Uninitialised Variables

To initialise a variable is to assign it a starting value. Although the program automatically initialises all variables (an empty string being the default value), it is good practice for a script to always initialise its variables before use. That way, anyone reading the script can see


what variables the script will be using and what starting values they are expected to have.

It is usually necessary for the script to initialise any variable which is expected to hold a number. For example, x := x + 1 will not
work if x has never been assigned a value, since the empty string is considered to be non-numeric. The script should have assigned a
starting value, such as x := 0. There are some cases where empty values are assumed to be 0, but it is best not to rely on this.

Script authors can use the #Warn directive to help find instances where a variable is used without having been initialised by the script.
Built-in Variables

A number of useful variables are built into the program and can be referenced by any script. With the exception of Clipboard,
ErrorLevel, and command line parameters, these variables are read-only; that is, their contents cannot be directly altered by the script.
By convention, most of these variables start with the prefix A_, so it is best to avoid using this prefix for your own variables.

Some variables such as A_KeyDelay and A_TitleMatchMode represent settings that control the script's behavior, and retain separate
values for each thread. This allows subroutines launched by new threads (such as for hotkeys, menus, timers and such) to change settings without affecting other threads.

Some special variables are not updated periodically, but rather their value is retrieved or calculated whenever the script references the
variable. For example, Clipboard retrieves the current contents of the clipboard as text, and A_TimeSinceThisHotkey calculates the
number of milliseconds that have elapsed since the hotkey was pressed.

Related: list of built-in variables.
Environment Variables

Environment variables are maintained by the operating system. You can see a list of them at the command prompt by typing SET then
pressing Enter.

A script may create a new environment variable or change the contents of an existing one with EnvSet. Such additions and changes are
not seen by the rest of the system. However, any programs or scripts which the script launches by calling Run or RunWait usually inherit a copy of the parent script's environment variables.

It is recommended that all new scripts retrieve environment variables such as Path via EnvGet:

EnvGet, OutputVar, Path  ; For explanation, see #NoEnv.

If a script lacks the #NoEnv directive, reading an empty variable will instead return the value of the environment variable with that
name, if there is one. This can cause confusion, so it is recommended that all new scripts use #NoEnv.

Caching

Although a variable is typically thought of as holding a single value, and that value having a distinct type (string, number or object),
AutoHotkey automatically converts between numbers and strings in cases like myString + 1 and MsgBox %myNumber%. As these
conversions can happen very frequently, whenever a variable is converted, the result is cached in the variable.

In effect, a variable can contain both a string and a number simultaneously. Usually this just improves the script's performance with no
down-sides, but if a variable contains both a number and a string, is it number, or is it a string? This ambiguity causes unexpected
behavior in at least two cases:

1. COM objects. In order to pass parameters to a COM object, the program must convert the variable's content to either a number or a
string. Some COM objects throw an exception if the wrong type of value is passed. If a variable has both, the number is used.

Usually this gets the right result, but sometimes it doesn't.

2. Objects don't have the capability to store both a number and a string as a key or value. Since numbers are more memory-efficient,

if a variable has both, the number is used (except for floating-point values used as keys).

SetFormat's slow mode forces the assignment of a pure number to immediately convert that number to a string. For integers, the number

is also stored, so this doesn't have adverse effects other than to performance. For floats, the number is not stored, since SetFormat affects the precision of the value, possibly even truncating all decimal places. In other words, SetFormat's slow mode prevents pure floats from being stored in variables.

Taking the address of a variable effectively converts the variable's value to a string, disabling caching until the variable's address changes (this happens when its capacity changes). This is both for backward-compatibility and because the script could change the value
indirectly via its address at any time, making the cache inaccurate.

Related

Variables: basic usage and examples.

Variable Capacity and Memory: details about limitations.


Functions/Commands

A function or command is the basic means by which a script does something.

In essence, functions and commands are the same thing, so the concepts explained here apply to both. However, the long history of
AutoHotkey v1 and an emphasis on backward-compatibility have resulted in a divide between commands, which require legacy syntax, and functions, which require expression syntax.

Commands and functions can have many different purposes. Some functions might do no more than perform a simple calculation, while others have immediately visible effects, such as moving a window. One of AutoHotkey's strengths is the ease with which scripts can
automate other programs and perform many other common tasks by simply calling a few functions. See the command and function list
for examples.

Throughout this documentation, some common words are used in ways that might not be obvious to someone without prior experience. Below are several such words/phrases which are used frequently in relation to functions and commands:

Call a function or command

Calling a function or command causes the program to invoke, execute or evaluate it. In other words, a function call temporarily

transfers control from the script to the function. When the function has completed its purpose, it returns control to the script. In
other words, any code following the function call does not execute until after the function completes.

However, sometimes a function or command completes before its effects can be seen by the user. For example, the Send command
sends keystrokes, but may return before the keystrokes reach their destination and cause their intended effect.

Parameters

Usually a command or function accepts parameters which tell it how to operate or what to operate on. Each parameter is a value,

such as a string or number. For example, WinMove moves a window, so its parameters tell it which window to move and where to
move it to. Parameters can also be called arguments. Common abbreviations include param and arg.

Pass parameters

Parameters are passed to a function or command, meaning that a value is specified for each parameter of the function or command

when it is called. For example, one can pass the name of a key to GetKeyState to determine whether that key is being held down.
Return a value

Functions return a value, so the result of the function is often called a return value. For example, StrLen returns the number of
characters in a string. Commands do not return a result directly; instead, they store the result in a variable. Functions may also do
this, such as when there is more than one result.

Functions and commands usually expect parameters to be written in a specific order, so the meaning of each parameter value depends on its position in the comma-delimited list of parameters. Some parameters can be omitted, in which case the parameter can be left blank,
but the comma following it can only be omitted if all remaining parameters are also omitted. For example, the syntax for ControlSend is:

ControlSend , Control, Keys, WinTitle, WinText, ExcludeTitle, ExcludeText

Square brackets signify that the enclosed parameters are optional (the brackets themselves should not appear in the actual code).
However, ControlSend isn't useful unless Keys are specified, and usually one must also specify the target window. For example:

ControlSend, Edit1, ^{Home}, A  ; Correct. Control is specified.
ControlSend, ^{Home}, A         ; Incorrect: Parameters are mismatched.
ControlSend,, ^{Home}, A        ; Correct. Control is omitted.

Methods

Methods are functions which operate on a particular object. While there can only be one function named Send (for example), there can be as many methods named Send as there are objects, as each object (or class of objects) can respond in a different way. For this reason, the target object (which may be a variable or sub-expression) is specified to left of the method name instead of inside the parameter list. For details, see Object Protocol.

Control Flow

Control flow is the order in which individual statements are executed. Normally statements are executed sequentially from top to bottom, but a control flow statement can override this, such as by specifying that statements should be executed repeatedly, or only if a certain
condition is met.

Statement

A statement is simply the smallest standalone element of the language that expresses some action to be carried out. In AutoHotkey,


statements include commands, assignments, function calls and other expressions. However, directives, labels (including hotkeys
and hotstrings), and declarations without assignments are not statements; they are processed when the program first starts up,
before the script executes.

Execute

Carry out, perform, evaluate, put into effect, etc. Execute basically has the same meaning as in non-programming speak.

Body

The body of a control flow statement is the statement or group of statements to which it applies. For example, the body of an if
statement is executed only if a specific condition is met.

For example, consider this simple set of instructions:
1. Open Notepad

2. Wait for Notepad to appear on the screen
3. Type "Hello, world!"

We take one step at a time, and when that step is finished, we move on to the next step. In the same way, control in a program or script
usually flows from one statement to the next statement. But what if we want to type into an existing Notepad window? Consider this
revised set of instructions:

1. If Notepad is not running:
1. Open Notepad

2. Wait for Notepad to appear on the screen
2. Otherwise:

1. Activate Notepad
3. Type "Hello, world!"

So we either open Notepad or activate Notepad depending on whether it is already running. #1 is a conditional statement, also known as an if statement; that is, we execute its body (#1.1 - #1.2) only if a condition is met. #2 is an else statement; we execute its body (#2.1)
only if the condition of a previous if statement (#1) is not met. Depending on the condition, control flows one of two ways: #1 (if true) → #1.1 → #1.2 → #3; or #1 (if false) → #2 (else) → #2.1 → #3.

The instructions above can be translated into the code below:

if (not WinExist("ahk_class Notepad"))

{

    Run Notepad

    WinWait ahk_class Notepad

}

else

    WinActivate ahk_class Notepad
Send Hello`, world!

In our written instructions, we used indentation and numbering to group the statements. Scripts work a little differently. Although
indentation makes code easier to read, in AutoHotkey it does not affect the grouping of statements. Instead, statements are grouped by
enclosing them in braces, as shown above. This is called a block.

For details about syntax - that is, how to write or recognise control flow statements in AutoHotkey - see Control Flow.
Details

String Encoding

Each character in the string is represented by a number, called its ordinal number, or character code. For example, the value "Abc"
would be represented as follows:

A        b         c
659899

The encoding of a string is the way in which numbers are mapped to symbols. There are many different encodings, but as all of those
supported by AutoHotkey include ASCII as a subset, character codes 0 to 127 always have the same meaning. For example, 'A' always
has the character code 65.

Although AutoHotkey provides ways to work with text in various encodings, the built-in commands and functions--and to some degree the language itself--all assume string values to be in one particular encoding. This is referred to as the native encoding. The native
encoding depends on the version of AutoHotkey:

Unicode versions of AutoHotkey use UTF-16. The smallest element in a UTF-16 string is two bytes (16 bits). Unicode characters
in the range 0 to 65535 (U+FFFF) are represented by a single 16-bit code unit of the same value, while characters in the range


65536 (U+10000) to 1114111 (U+10FFFF) are represented by a surrogate pair; that is, exactly two 16-bit code units between
0xD800 and 0xDFFF. (For further explanation of surrogate pairs and methods of encoding or decoding them, search the Internet.)

ANSI versions of AutoHotkey use the system default ANSI code page, which depends on the system locale or "language for non-
Unicode programs" system setting. The smallest element of an ANSI string is one byte. However, some code pages contain
characters which are represented by sequences of multiple bytes (these are always non-ASCII characters).

Generally, other parts of this documentation use the term "character" to mean a string's smallest unit; bytes for ANSI strings and 16-bit code units for Unicode strings. For practical reasons, the length of a string and positions within a string are measured by counting these fixed-size units, even though they may not be complete Unicode characters.

FileRead, FileAppend, FileOpen and the File object provide ways of reading and writing text in files with a specific encoding.

The functions StrGet and StrPut can be used to convert strings between the native encoding and some other specified encoding.
However, these are usually only useful in combination with data structures and the DllCall function. Strings which are passed directly to or from DllCall can be converted to ANSI or UTF-16 by using the AStr or WStr parameter types.

Techniques for dealing with the differences between ANSI and Unicode versions of AutoHotkey can be found under Unicode vs ANSI. Pure Numbers

A pure or binary number is one which is stored in memory in a format that the computer's CPU can directly work with, such as to
perform math. In most cases, AutoHotkey automatically converts between numeric strings and pure numbers as needed, and rarely
differentiates between the two types. AutoHotkey primarily uses two data types for pure numbers:

64-bit signed integers (int64).

64-bit binary floating-point numbers (the double or binary64 format of the IEEE 754 international standard).

In other words, scripts are affected by the following limitations:

Integers must be within the range -9223372036854775808 (-0x8000000000000000, or -263) to 9223372036854775807

(0x7FFFFFFFFFFFFFFF, or 263-1). Although larger values can be contained within a string, any attempt to convert the string to a
number (such as by using it in a math operation) might yield inconsistent results.

Floating-point numbers generally support 15 digits of precision. However, converting a floating-point number to a string causes
the number to be rounded according to the current float format, which defaults to 6 decimal places. If the "slow" mode of
SetFormat is present anywhere in the script, numbers are always converted to strings when assigned to a variable.

Note: There are some decimal fractions which the binary floating-point format cannot precisely represent, so a number is rounded to the closest representable number. This may lead to unexpected results. For example:

SetFormat FloatFast, 0.17  ; Show "over-full" precision
MsgBox % 0.1 + 0           ; 0.10000000000000001

MsgBox % 0.1 + 0.2         ; 0.30000000000000004

MsgBox % 0.3 + 0           ; 0.29999999999999999

MsgBox % 0.1 + 0.2 = 0.3   ; 0 (not equal)

One strategy for dealing with this is to avoid direct comparison, instead comparing the difference. For example:

MsgBox % Abs((0.1 + 0.2) - (0.3)) < 0.0000000000000001

Another strategy is to always convert to string (thereby applying rounding) before comparison. There are generally two ways to do this while specifying the precision, and both are shown below:

MsgBox % Round(0.1 + 0.2, 15) = Format("{:.15f}", 0.3)
Names

AutoHotkey uses the same set of rules for naming various things, including variables, functions, window groups, GUIs, classes and
methods:

Case sensitivity: None for ASCII characters. For example, CurrentDate is the same as currentdate. However, uppercase non-
ASCII characters such as 'Ä' are not considered equal to their lowercase counterparts, regardless of the current user's locale. This
helps the script to behave consistently across multiple locales.

Maximum length: 253 characters.

Allowed characters: Letters, numbers, non-ASCII characters, and the following symbols: _ # @ $

Due to style conventions, it is generally better to name your variables using only letters, numbers, and the underscore character (for
example: CursorPosition, Total_Items, and entry_is_valid). This style allows people familiar with other computer languages to
understand your scripts more easily.

Although a variable name may consist entirely of digits, this is generally used only for incoming command line parameters. Such


numeric names cannot be used in expressions because they would be seen as numbers rather than variables. It is best to avoid starting a
name with a digit, as such names are confusing and will be considered invalid in AutoHotkey v2.

As the following characters may be reserved for other purposes in AutoHotkey v2, it is recommended to avoid using them: # @ $
Property names in classes have the same rules and restrictions as variable names, except that the three characters listed above (# @ $) are not allowed. Although they can be used in a method definition, calling such a method requires using square brackets. For example,
myObject.@home() is not valid, but myObject["@home"]() is acceptable.

Variable References vs Values

Variables have certain attributes that blur the line between a variable and its value, but it is important to make the distinction. In
particular, consider objects and ByRef parameters.

Although we may say the variable myArray contains an array (which is a type of object), what the variable contains isn't the array itself
but rather a reference or pointer to the array. Any number of variables can contain a reference to the same object. It may be helpful to
think of a variable as just a name in that case. For instance, giving a person a nickname doesn't cause a clone of that person to come into existence.

By default, variables are passed to user-defined functions by value. In other words, the value contained by the variable is copied into the variable which corresponds to the function's parameter. ByRef parameters allow you to pass a variable by reference, or in other words, to make one parameter of the function an alias for your variable, allowing the function to assign a new value to your variable.

Because a variable only ever contains a reference to an object and not the object itself, when you pass such a variable to a non-ByRef
parameter, what the function receives is a reference to the same object. This allows the function to modify the object, but it does not
allow the function to modify the variable which the function's caller used, because the function only has a reference to the object, not the variable.

References to Objects

Scripts interact with an object only indirectly, through a reference to the object. When you create an object, the object is created at some location you don't control, and you're given a reference. Passing this reference to a function or storing it in a variable or another object
creates a new reference to the same object. You release a reference by simply using an assignment to replace it with any other value. An object is deleted only after all references have been released; you cannot delete an object explicitly, and should not try.

ref1 := Object()  ; Create an object and store first reference

ref2 := ref1      ; Create a new reference to the same object

ref1 := ""        ; Release the first reference

ref2 := ""        ; Release the second reference; object is deleted

If that's difficult to understand, try thinking of an object as a rental unit. When you rent a unit, you're given a key which you can use to
access the unit. You can get more keys and use them to access the same unit, but when you're finished with the unit, you must hand all
keys back to the rental agent. Usually a unit wouldn't be deleted, but maybe the agent will have any junk you left behind removed; just as

any values you stored in an object are freed when the object is deleted.


Frequently Asked Questions (FAQ)

Table of Contents

Language Syntax

When are quotation marks used with commands and their parameters?

When exactly are variable names enclosed in percent signs?
When should percent signs and commas be escaped?

General Troubleshooting

What can I do if AutoHotkey won't install?

Why do some lines in my script never execute?

Why doesn't my script work on Windows xxx even though it worked on a previous version?

How do I work around problems caused by User Account Control (UAC)?

I can't edit my script via tray icon because it won't start due to an error. Can I find my script somewhere else?
How can I find and fix errors in my code?

Why is the Run command unable to launch my game or program?

Why are the non-ASCII characters in my script displaying or sending incorrectly?

Why don't Hotstrings, Send, and MouseClick work in certain games?

How can performance be improved for games or at other times when the CPU is under heavy load?

My antivirus program flagged AHK as malware. Does it really contain a virus?

Common Tasks

Where can I find the official build, or older releases?

Can I run AHK from a USB drive?

How can the output of a command line operation be retrieved?

How can a script close, pause, or suspend other script(s)?

How can a repeating action be stopped without exiting the script?

How can context sensitive help for AutoHotkey commands be used in any editor?

How to detect when a web page is finished loading?

How can dates and times be compared or manipulated?

How can I send the current Date and/or Time?

How can I send text to a window which isn't active or isn't visible?

How can Winamp be controlled even when it isn't active?

How can MsgBox's button names be changed?

How can I change the default editor, which is accessible via context menu or tray icon?
How can I save the contents of my GUI associated variables?

Can I draw something with AHK?

How can I start an action when a window appears, closes or becomes [in]active?

Hotkeys, Hotstrings, and Remapping

How do I put my hotkeys and hotstrings into effect automatically every time I start my PC?

I'm having trouble getting my mouse buttons working as hotkeys. Any advice?

How can tab and space be defined as hotkeys?

How can keys or mouse buttons be remapped so that they become different keys?

How do I detect the double press of a key or button?

How can a hotkey or hotstring be made exclusive to certain program(s)? In other words, I want a certain key to act as it normally
does except when a specific window is active.

How can a prefix key be made to perform its native function rather than doing nothing?

How can the built-in Windows shortcut keys, such as Win+U (Utility Manager) and Win+R (Run), be changed or disabled?

Can I use wildcards or regular expressions in Hotstrings?

How can I use a hotkey that is not in my keyboard layout?

My keypad has a special 000 key. Is it possible to turn it into a hotkey?

Language Syntax

When are quotation marks used with commands and their parameters?

Double quotes (") have special meaning only within expressions. In all other places, they are treated literally as if they were normal
characters. However, when a script launches a program or document, the operating system usually requires quotes around any command- line parameter that contains spaces, such as in this example: Run, Notepad.exe "C:\My Documents\Address List.txt".

When exactly are variable names enclosed in percent signs?


Variable names are always enclosed in percent signs except in cases illustrated in bold below:
1) In parameters that are input or output variables: StringLen, OutputVar, InputVar

2) On the left side of an assignment: Var = 123abc

3) On the left side of traditional (non-expression) if-statements: If Var1 < %Var2%

4) Everywhere in expressions. For example:

If (Var1 <> Var2)
    Var1 := Var2 + 100

When should percent signs and commas be escaped?

Literal percent signs must be escaped by preceding them with an accent/backtick. For example: MsgBox The current percentage is
25`%. Literal commas must also be escaped (`,) except when used in MsgBox or the last parameter of any command (in which case the accent is permitted but not necessary).

When commas or percent signs are enclosed in quotes within an expression, the accent is permitted but not necessary. For example: Var := "15%".

General Troubleshooting

What can I do if AutoHotkey won't install?

7-zip Error: Use 7-zip or a compatible program to extract the setup files from the installer EXE, then run setup.exe or Installer.ahk (drag and drop Installer.ahk onto AutoHotkeyU32.exe).

AutoHotkey's installer comes packaged as a 7-zip self-extracting archive which attempts to extract to the user's Temp directory and
execute a compiled script. Sometimes system policies or other factors prevent the files from being extracted or executed. Usually in such cases the message "7-zip Error" is displayed. Manually extracting the files to a different directory may help.

Setup hangs: If the setup window comes up blank or not at all, try one or both of the following:

Hold Ctrl or Shift when the installer starts. If you get a UAC prompt, hold Ctrl or Shift as you click Yes/Continue. You should

get a prompt asking whether you want to install with default options.

Install using command line options. If you have manually extracted the setup files from the installer EXE, use either setup.exe
/S or AutoHotkeyU32.exe Installer.ahk /S.

Other: The suggestions above cover the most common problems. For further assistance, post on the forums.
Why do some lines in my script never execute?

Any lines you want to execute immediately when the script starts should appear at the top of the script, prior to the first hotkey,
hotstring, or Return. For details, see auto-execute section.

Also, a hotkey that executes more than one line must list its first line beneath the hotkey, not on the same line. For example:

#space::  ; Win+Spacebar

Run Notepad

WinWaitActive Untitled - Notepad
WinMaximize

return

Why doesn't my script work on Windows xxx even though it worked on a previous version?

There are many variations of this problem, such as:

I've upgraded my computer/Windows and now my script won't work.

Hotkeys/hotstrings don't work when a program running as admin is active.
Some windows refuse to be automated (e.g. Device Manager ignores Send).

If you've switched operating systems, it is likely that something else has also changed and may be affecting your script. For instance, if
you've got a new computer, it might have different drivers or other software installed. If you've also updated to a newer version of
AutoHotkey, find out which version you had before and then check the changelog and compatibility notes.

SoundGet, SoundSet, SoundGetWaveVolume and SoundSetWaveVolume behave differently on Vista and later than on earlier versions of Windows. In particular, device numbers are different and some components may be unavailable. Behaviour depends on the audio
drivers, which are necessarily different to the ones used on XP. The soundcard analysis script can be used to find the correct device
numbers.

Also refer to the following question:


How do I work around problems caused by User Account Control (UAC)?

User Account Control (UAC) is a common cause of problems, especially when moving from Windows XP/Vista/7 to Vista/7/8/10.
Although it is present in Windows Vista and later, it is enabled by default on new systems or new installs, and it is more difficult to
disable on Windows 8 and later.

By default, UAC protects "elevated" programs (that is, programs which are running as admin) from being automated by non-elevated
programs, since that would allow them to bypass security restrictions. Hotkeys are also blocked, so for instance, a non-elevated program cannot spy on input intended for an elevated program.

UAC may also prevent SendPlay and BlockInput from working.
Common workarounds are as follows:

Enable the Add 'Run with UI Access' to context menus option in AutoHotkey Setup. This option can be enabled or disabled without
reinstalling AutoHotkey by re-running AutoHotkey Setup from the Start menu. Once it is enabled, launch your script file by right-
clicking it and selecting Run with UI Access, or use a command line like "AutoHotkeyU32_UIA.exe" "Your script.ahk" (but
include full paths).

Run the script as administrator. Note that this also causes any programs launched by the script to run as administrator, and may
require the user to accept an approval prompt when launching the script.

Disable the local security policy "Run all administrators in Admin Approval Mode" (not recommended).

Disable UAC completely. This is not recommended, and is not feasible on Windows 8 or later.

I can't edit my script via tray icon because it won't start due to an error. What do I do?

You need to fix the error in your script before you can get your tray icon back. But first, you need to find the script file.
Look for AutoHotkey.ahk in the following directories:

Your Documents (or My Documents) folder.

The directory where you installed AutoHotkey, usually C:\Program Files\AutoHotkey. If you are using AutoHotkey without
having installed it, look in the directory which contains AutoHotkey.exe.

If you are running another AutoHotkey executable directly, the name of the script depends on the executable. For example, if you are
running AutoHotkeyU32.exe, look for AutoHotkeyU32.ahk. Note that depending on your system settings the ".ahk" part may be hidden, but the file should have an icon like 

You can usually edit a script file by right clicking it and selecting Edit Script. If that doesn't work, you can open the file in Notepad or
another editor.

If you launch AutoHotkey from the Start menu or by running AutoHotkey.exe directly (without command line parameters), it will look
for a script in one of the locations shown above. Alternatively, you can create a script file (something.ahk) anywhere you like, and run
the script file instead of running AutoHotkey.

See also Command Line Parameter "Script Filename" and Portability of AutoHotkey.exe.
How can I find and fix errors in my code?

For simple scripts, see Debugging a Script. To show contents of a variable, use MsgBox or ToolTip. For complex scripts, see Interactive Debugging.

Why is the Run command unable to launch my game or program?

Some programs need to be started in their own directories (when in doubt, it is usually best to do so). For example:

Run, %A_ProgramFiles%\Some Application\App.exe, %A_ProgramFiles%\Some Application

If the program you are trying to start is in %A_WinDir%\System32 and you are using AutoHotkey 32-bit on a 64-bit system, the File
System Redirector may be interfering. To work around this, use %A_WinDir%\SysNative instead; this is a virtual directory only visible to 32-bit programs running on 64-bit systems.

Why are the non-ASCII characters in my script displaying or sending incorrectly?

Short answer: Save the script as UTF-8 with BOM.

Although AutoHotkey supports Unicode text, it is optimized for backward-compatibility, which means defaulting to the ANSI encoding rather than the more internationally recommended UTF-8. AutoHotkey will not automatically recognize a UTF-8 file unless it begins
with a byte order mark.

In other words, UTF-8 files which lack a byte order mark are misinterpreted, causing non-ASCII characters to be decoded incorrectly.


To resolve this, save the file as UTF-8 with BOM or add the /CP65001 command line switch.

To save as UTF-8 with BOM in Notepad, select UTF-8 from the Encoding drop-down in the Save As dialog.

To read other UTF-8 files which lack a byte order mark, use FileEncoding UTF-8-RAW, the *P65001 option with FileRead, or "UTF-8- RAW" for the third parameter of FileOpen. The -RAW suffix can be omitted, but in that case any newly created files will have a byte order mark.

Note that INI files accessed with the standard INI commands do not support UTF-8; they must be saved as ANSI or UTF-16.
Why do Hotstrings, Send, and Click have no effect in certain games?

Not all games allow AHK to send keys and clicks or receive pixel colors.

But there are some alternatives, try all the solutions mentioned below. If all these fail, it may not be possible for AHK to work with your game. Sometimes games have a hack and cheat prevention measure, such as GameGuard and Hackshield. If they do, there is a high
chance that AutoHotkey will not work with that game.

Use SendPlay via the SendPlay command, SendMode Play and/or the hotstring option SP.

SendPlay, abc
SendMode, Play
Send, abc

:SP:btw::by the way
; or

#Hotstring SP
::btw::by the way

Note: SendPlay may have no effect at all on Windows Vista or later if User Account Control is enabled, even if the script is
running as an administrator.

Increase SetKeyDelay. For example:

SetKeyDelay, 0, 50
SetKeyDelay, 0, 50, Play

Try ControlSend, which might work in cases where the other Send modes fail:

ControlSend,, abc, game_title

Try the down and up event of a key with the various send methods:

Send {KEY down}{KEY up}

Try the down and up event of a key with a Sleep between them:

Send {KEY down}

Sleep 10 ; try various milliseconds
Send {KEY up}

How can performance be improved for games or at other times when the CPU is under heavy load?

If a script's Hotkeys, Clicks, or Sends are noticeably slower than normal while the CPU is under heavy load, raising the script's process- priority may help. To do this, include the following line near the top of the script:

Process, Priority, , High

My antivirus program flagged AutoHotkey or a compiled script as malware. Is it really a virus?

Although it is certainly possible that the file has been infected, most often these alerts are false positives, meaning that the antivirus
program is mistaken. One common suggestion is to upload the file to an online service such as virustotal or Jotti and see what other
antivirus programs have to say. If in doubt, you could send the file to the vendor of your antivirus software for confirmation. This might

also help us and other AutoHotkey users, as the vendor may confirm it is a false positive and fix their product to play nice with
AutoHotkey.

False positives might be more common for compiled scripts which have been compressed, such as with UPX (default for AutoHotkey
1.0 but not 1.1) or MPRESS (optional for AutoHotkey 1.1). As the default AutoHotkey installation does not include a compressor,
compiled scripts are not compressed by default.

Common Tasks


Where can I find the official build, or older releases?

See download page of AutoHotkey.

Can I run AHK from a USB drive?

See Portability of AutoHotkey.exe. Note that if you use auto-included function libraries, AutoHotkey.exe and the Lib folder must be up one level from Ahk2Exe.exe (e.g. \AutoHotkey.exe vs \Compiler\Ahk2Exe.exe). Also note that Ahk2Exe saves settings to the following registry key: HKCU\Software\AutoHotkey\Ahk2Exe.

How can the output of a command line operation be retrieved?

Testing shows that due to file caching, a temporary file can be very fast for relatively small outputs. In fact, if the file is deleted
immediately after use, it often does not actually get written to disk. For example:

RunWait %ComSpec% /c dir > C:\My Temp File.txt
FileRead, VarToContainContents, C:\My Temp File.txt
FileDelete, C:\My Temp File.txt

To avoid using a temporary file (especially if the output is large), consider using the Shell.Exec() method as shown in the examples for the Run command.

How can a script close, pause, or suspend other script(s)?

First, here is an example that closes another script:

DetectHiddenWindows On  ; Allows a script's hidden main window to be detected.

SetTitleMatchMode 2  ; Avoids the need to specify the full path of the file below.

WinClose Script's File Name.ahk - AutoHotkey  ; Update this to reflect the script's name (case sensitive).

To suspend or pause another script, replace the last line above with one of these:

PostMessage, 0x111, 65305,,, Script's File Name.ahk - AutoHotkey  ; Suspend.
PostMessage, 0x111, 65306,,, Script's File Name.ahk - AutoHotkey  ; Pause.

How can a repeating action be stopped without exiting the script?

To pause or resume the entire script at the press of a key, assign a hotkey to the Pause command as in this example:

^!p::Pause  ; Press Ctrl+Alt+P to pause. Press it again to resume.

To stop an action that is repeating inside a Loop, consider the following working example, which is a hotkey that both starts and stops its own repeating action. In other words, pressing the hotkey once will start the Loop. Pressing the same hotkey again will stop it.

#MaxThreadsPerHotkey 3

#z::  ; Win+Z hotkey (change this hotkey to suit your preferences).

#MaxThreadsPerHotkey 1

if KeepWinZRunning  ; This means an underlying thread is already running the loop below.

{

    KeepWinZRunning := false  ; Signal that thread's loop to stop.

    return  ; End this thread so that the one underneath will resume and see the change made by the line above.

}

; Otherwise:
KeepWinZRunning := true
Loop

{

    ; The next four lines are the action you want to repeat (update them to suit your preferences):
    ToolTip, Press Win-Z again to stop this from flashing.

    Sleep 1000

    ToolTip

    Sleep 1000

    ; But leave the rest below unchanged.

    if not KeepWinZRunning  ; The user signaled the loop to stop by pressing Win-Z again.
        break  ; Break out of this loop.

}

KeepWinZRunning := false  ; Reset in preparation for the next press of this hotkey.
return

How can context sensitive help for AutoHotkey commands be used in any editor?

Rajat created this script.

How to detect when a web page is finished loading?

With Internet Explorer, perhaps the most reliable method is to use DllCall and COM as demonstrated at
www.autohotkey.com/forum/topic19256.html. On a related note, the contents of the address bar and status bar can be retrieved as


demonstrated at www.autohotkey.com/forum/topic19255.html.

Older, less reliable method: The technique in the following example will work with MS Internet Explorer for most pages. A similar technique might work in other browsers:

Run, www.yahoo.com

MouseMove, 0, 0  ; Prevents the status bar from showing a mouse-hover link instead of "Done".
WinWait, Yahoo! - 

WinActivate 

StatusBarWait, Done, 30

if ErrorLevel

    MsgBox The wait timed out or the window was closed. 

else 

    MsgBox The page is done loading.

How can dates and times be compared or manipulated?

The EnvAdd command can add or subtract a quantity of days, hours, minutes, or seconds to a time-string that is in the
YYYYMMDDHH24MISS format. The following example subtracts 7 days from the specified time: EnvAdd,
VarContainingTimestamp, -7, days.

To determine the amount of time between two dates or times, see EnvSub, which gives an example. Also, the built-in variable A_Now contains the current local time. Finally, there are several built-in date/time variables, as well as the FormatTime command to create a custom date/time string.

How can I send the current Date and/or Time?

Use FormatTime or built-in variables for date and time.

How can I send text to a window which isn't active or isn't visible?

Use ControlSend.

How can Winamp be controlled even when it isn't active?

See Automating Winamp.

How can MsgBox's button names be changed?

Here is an example.

How can I change the default editor, which is accessible via context menu or tray icon?

In the example section of Edit you will find a script that allows you to change the default editor.
How can I save the contents of my GUI associated variables?

Use Gui Submit. For Example:

Gui, Add, Text,, Enter some Text and press Submit:
Gui, Add, Edit, vAssociatedVar

Gui, Add, Button,, Submit

Gui, Show

Return

ButtonSubmit:

Gui, Submit, NoHide

MsgBox, Content of the edit control: %AssociatedVar%
Return

Can I draw something with AHK?

See GDI+ standard library by tic. It's also possible with some rudimentary methods using Gui, but in a limited way.
How can I start an action when a window appears, closes or becomes [in]active?

Use WinWait, WinWaitClose or WinWait[Not]Active.

There are also user-created solutions such as OnWin.ahk and [How to] Hook on to Shell to receive its messages.
Hotkeys, Hotstrings, and Remapping


How do I put my hotkeys and hotstrings into effect automatically every time I start my PC?

There are several ways to make a script (or any program) launch automatically every time you start your PC. The easiest is to place a
shortcut to the script in the Startup folder:

1. Find the script file, select it, and press Control+C.

2. Press Win+R to open the Run dialog, then enter shell:startup and click OK or Enter. This will open the Startup folder for the

current user. To instead open the folder for all users, enter shell:common startup (however, in that case you must be an
administrator to proceed).

3. Right click inside the window, and click "Paste Shortcut". The shortcut to the script should now be in the Startup folder.
I'm having trouble getting my mouse buttons working as hotkeys. Any advice?

The left and right mouse buttons should be assignable normally (for example, #LButton:: is the Win+LeftButton hotkey). Similarly, the middle button and the turning of the mouse wheel should be assignable normally except on mice whose drivers directly control those
buttons.

The fourth button (XButton1) and the fifth button (XButton2) might be assignable if your mouse driver allows their clicks to be seen by the system. If they cannot be seen -- or if your mouse has more than five buttons that you want to use -- you can try configuring the
software that came with the mouse (sometimes accessible in the Control Panel or Start Menu) to send a keystroke whenever you press
one of these buttons. Such a keystroke can then be defined as a hotkey in a script. For example, if you configure the fourth button to send Control+F1, you can then indirectly configure that button as a hotkey by using ^F1:: in a script.

If you have a five-button mouse whose fourth and fifth buttons cannot be seen, you can try changing your mouse driver to the default
driver included with the OS. This assumes there is such a driver for your particular mouse and that you can live without the features
provided by your mouse's custom software.

How can Tab and Space be defined as hotkeys?

Use the names of the keys (Tab and Space) rather than their characters. For example, #Space is Win+Space and ^!Tab is
Control+Alt+Tab.

How can keys or mouse buttons be remapped so that they become different keys?

This is described on the remapping page.

How do I detect the double press of a key or button?

Use built-in variables for hotkeys as follows:

~Ctrl::

    if (A_ThisHotkey = A_PriorHotkey && A_TimeSincePriorHotkey < 200)
        MsgBox double-press

return

How can a hotkey or hotstring be made exclusive to certain program(s)? In other words, I want a certain
key to act as it normally does except when a specific window is active.

The preferred method is #IfWinActive. For example:

#IfWinActive, ahk_class Notepad

^a::MsgBox You pressed Control-A while Notepad is active.

How can a prefix key be made to perform its native function rather than doing nothing?

Consider the following example, which makes Numpad0 into a prefix key:

Numpad0 & Numpad1::MsgBox, You pressed Numpad1 while holding down Numpad0.

Now, to make Numpad0 send a real Numpad0 keystroke whenever it wasn't used to launch a hotkey such as the above, add the following hotkey:

 $Numpad0::Send, {Numpad0}

The $ prefix is needed to prevent a warning dialog about an infinite loop (since the hotkey "sends itself"). In addition, the above action
occurs at the time the key is released.

How can the built-in Windows shortcut keys, such as Win+U (Utility Manager) and Win+R (Run), be
changed or disabled?

Here are some examples.


Can I use wildcards or regular expressions in Hotstrings?

Use the script by polyethene (examples are included).

How can I use a hotkey that is not in my keyboard layout?

See Special Keys.

My keypad has a special 000 key. Is it possible to turn it into a hotkey?

Yes. This example script makes the 000 key into an equals key. You can change the action by replacing the Send, = line with line(s) of your choice.


Functions

Table of Contents

Introduction and Simple Examples

Parameters

Optional Parameters

Returning Values to Caller

Variadic Functions

Local Variables

Dynamically Calling a Function

Short-circuit Boolean Evaluation

Using Subroutines Within a Function

Return, Exit, and General Remarks

Using #Include to Share Functions Among Multiple Scripts
Libraries of Functions: Standard Library and User Library
Built-in Functions

Introduction and Simple Examples

A function is similar to a subroutine (Gosub) except that it can accept parameters (inputs) from its caller. In addition, a function may
optionally return a value to its caller. Consider the following simple function that accepts two numbers and returns their sum:

Add(x, y)

{

    return x + y   ; "Return" expects an expression.

}

The above is known as a function definition because it creates a function named "Add" (not case sensitive) and establishes that anyone
who calls it must provide exactly two parameters (x and y). To call the function, assign its result to a variable with the := operator. For
example:

Var := Add(2, 3)  ; The number 5 will be stored in Var.
Also, a function may be called without storing its return value:

Add(2, 3)

But in this case, any value returned by the function is discarded; so unless the function produces some effect other than its return value, the call would serve no purpose.

Since a function call is an expression, any variable names in its parameter list should not be enclosed in percent signs. By contrast, literal strings should be enclosed in double quotes. For example:

if InStr(MyVar, "fox")

    MsgBox The variable MyVar contains the word fox.

Finally, functions may be called in the parameters of any command (except OutputVar and InputVar parameters such as those of
StringLen). However, parameters that do not support expressions must use the "% " prefix as in this example:

MsgBox % "The answer is: " . Add(3, 2)

The "% " prefix is also permitted in parameters that natively support expressions, but it is simply ignored.
Parameters

When a function is defined, its parameters are listed in parentheses next to its name (there must be no spaces between its name and the
open-parenthesis). If a function does not accept any parameters, leave the parentheses empty; for example: GetCurrentTimestamp().

ByRef Parameters: From the function's point of view, parameters are essentially the same as local variables unless they are defined as ByRef as in this example:

Swap(ByRef Left, ByRef Right)

{

    temp := Left
    Left := Right
    Right := temp

}

In the example above, the use of ByRef causes each parameter to become an alias for the variable passed in from the caller. In other
words, the parameter and the caller's variable both refer to the same contents in memory. This allows the Swap function to alter the


caller's variables by moving Left's contents into Right and vice versa.

By contrast, if ByRef were not used in the example above, Left and Right would be copies of the caller's variables and thus the Swap
function would have no external effect.

Since return can send back only one value to a function's caller, ByRef can be used to send back extra results. This is achieved by having the caller pass in a variable (usually empty) in which the function stores a value.

When passing large strings to a function, ByRef enhances performance and conserves memory by avoiding the need to make a copy of
the string. Similarly, using ByRef to send a long string back to the caller usually performs better than something like Return
HugeString.

[AHK_L 60+]: If something other than a modifiable variable is passed to a ByRef parameter, the function behaves as though the
keyword "ByRef" is absent. For example, Swap(A_Index, i) stores the value of A_Index in i, but the value assigned to Left is discarded once the Swap function returns.

[v1.1.01+]: The IsByRef() function can be used to determine whether the caller supplied a variable for a given ByRef parameter.
Known limitations:

Fields of objects are not considered variables for the purposes of ByRef. For example, if foo.bar is passed to a ByRef parameter, it
will behave as though ByRef was omitted.

It is not possible to pass Clipboard, built-in variables, or environment variables to a function's ByRef parameter, even when

#NoEnv is absent from the script.

Although a function may call itself recursively, if it passes one of its own local variables or non-ByRef parameters to itself ByRef,
the new layer's ByRef parameter will refer to its own local variable of that name rather than the previous layer's. However, this
issue does not occur when a function passes to itself a global variable, static variable, or ByRef parameter.

If a parameter in a function-call resolves to a variable (e.g. Var or ++Var or Var*=2), other parameters to its left or right can alter
that variable before it is passed to the function. For example, MyFunc(Var, Var++) would unexpectedly pass 1 and 0 when Var is
initially 0, even when the function's first parameter is not ByRef. Since this behavior is counterintuitive, it might change in a future
release.

ByRef is not directly supported in functions called by COM clients, or when calling COM methods. Instead, the script receives or
must pass a wrapper object containing the VarType and address of the value.

Optional Parameters

When defining a function, one or more of its parameters can be marked as optional. This is done by appending := (in [v1.1.09] or later)
or =, followed by the parameter's default value, which must be one of the following: true, false, a literal integer, a literal floating point number, or a quoted/literal string such as "fox" or "" (but strings in versions prior to [v1.0.46.13] support only "").

The use of = (without a colon) is permitted for backward-compatibility, but not recommended, and will not be permitted by AutoHotkey v2. Regardless of which operator is used, default values which are strings must always be enclosed in quote marks.

The following function has its Z parameter marked optional:

Add(X, Y, Z:=0) {
    return X + Y + Z

}

When the caller passes three parameters to the function above, Z's default value is ignored. But when the caller passes only two
parameters, Z automatically receives the value 0.

It is not possible to have optional parameters isolated in the middle of the parameter list. In other words, all parameters that lie to the
right of the first optional parameter must also be marked optional. [AHK_L 31+]: Optional parameters may be omitted from the middle of the parameter list when calling the function, as shown below. For dynamic function calls and method calls, this requires [v1.1.12+].

MyFunc(1,, 3)

MyFunc(X, Y:=2, Z:=0) {  ; Note that Z must still be optional in this case.
    MsgBox %X%, %Y%, %Z%

}

[v1.0.46.13+]: ByRef parameters also support default values; for example: MyFunc(ByRef p1 = ""). Whenever the caller omits such a parameter, the function creates a local variable to contain the default value; in other words, the function behaves as though the keyword "ByRef" is absent.

Returning Values to Caller

As described in introduction, a function may optionally return a value to its caller.

Test := returnTest()
MsgBox % Test


returnTest() {
    return 123

}

If you want to return extra results from a function, you may also use ByRef:

returnByRef(A,B,C)
MsgBox % A "," B "," C

returnByRef(ByRef val1, ByRef val2, ByRef val3)

{

    val1 := "A"
    val2 := 100
    val3 := 1.1
    return

}

[v1.0.97+]: Objects and Arrays can be used to return multiple values or even named values:

Test1 := returnArray1()

MsgBox % Test1[1] "," Test1[2]

Test2 := returnArray2()

MsgBox % Test2[1] "," Test2[2]

Test3 := returnObject()

MsgBox % Test3.id "," Test3.val

returnArray1() {
    Test := [123,"ABC"]
    return Test

}

returnArray2() {
    x := 456

    y := "EFG"
    return [x, y]

}

returnObject() {

    Test := {id: 789, val: "HIJ"}
    return Test

}

Variadic Functions [AHK_L 60+]

When defining a function, write an asterisk after the final parameter to mark the function as variadic, allowing it to receive a variable
number of parameters:

Join(sep, params*) {

    for index,param in params
        str .= param . sep

    return SubStr(str, 1, -StrLen(sep))

}

MsgBox % Join("`n", "one", "two", "three")

When a variadic function is called, surplus parameters can be accessed via an object which is stored in the function's final parameter. The first surplus parameter is at params[1], the second at params[2] and so on. As with any standard object, params.MaxIndex() can be
used to determine the highest numeric index (in this case the number of parameters). However, if there are no parameters, MaxIndex
returns an empty string.

Notes:

The "variadic" parameter can only appear at the end of the formal parameter list.
RegEx callouts cannot be variadic; the "variadic" parameter is tolerated but left blank.
Callbacks pass surplus parameters by address rather than via an array.

Variadic Function Calls

While variadic functions can accept a variable number of parameters, an array of parameters can be passed to any function by applying
the same syntax to a function-call:

substrings := ["one", "two", "three"]
MsgBox % Join("`n", substrings*)

Notes:

Numbering of parameters within the source array begins at 1.
Optional parameters may be entirely omitted from the array.


The array of parameters may contain named items when calling a user-defined function; in any other case, named items are not
supported.

The target function may also be variadic, in which case named items are copied even if they have no corresponding formal
parameter.

This syntax can also be used when calling methods or retrieving properties of objects; for example, Object.Property[Params*].
[v1.1.12+]: It can also be used for setting properties.

Known limitations:

Only the right-most parameter can be expanded this way. For example, MyFunc(x, y*) is supported but MyFunc(x*, y) is not.

There must not be any non-whitespace characters between the asterisk (*) and the symbol which ends the parameter list.
Local and Global Variables

Local Variables

Local variables are specific to a single function and are visible only inside that function. Consequently, a local variable may have the
same name as a global variable and both will have separate contents. Separate functions may also safely use the same variable names.

All local variables which are not static are automatically freed (made empty) when the function returns.

Built-in variables such as Clipboard, ErrorLevel, and A_TimeIdle are never local (they can be accessed from anywhere), and cannot be
redeclared.

Functions are assume-local by default. Variables accessed or created inside an assume-local function are local by default, with the
following exceptions:

Super-global variables, including classes.

A dynamic variable reference may resolve to an existing global variable if no local variable exists by that name.
Commands that create pseudo-arrays may create all elements as global even if only the first element is declared.

The default may also be overridden as shown below (by declaring the variable or by changing the mode of the function).

Force-local mode [v1.1.27+]: If the function's first line is the word "local", all variable references (even dynamic ones) are assumed to
be local unless they are declared as global inside the function. Unlike the default mode, force-local mode has the following behavior:

Super-global variables (including classes) cannot be accessed without declaring them inside the function.

Dynamic variable references follow the same rules as non-dynamic ones. Only global variables which are declared inside the
function can be accessed.

StringSplit and other commands which create pseudo-arrays follow the same rules as non-dynamic variable references (avoiding a
common source of confusion).

The LocalSameAsGlobal warning is never raised for variables within a force-local function.

Global variables

To refer to an existing global variable inside a function (or create a new one), declare the variable as global prior to using it. For example:

LogToFile(TextToLog)

{

    global LogFileName  ; This global variable was previously given a value somewhere outside this function.
    FileAppend, %TextToLog%`n, %LogFileName%

}

Assume-global mode: If a function needs to access or create a large number of global variables, it can be defined to assume that all its
variables are global (except its parameters) by making its first line either the word "global" or the declaration of a local variable. For
example:

SetDefaults()

{

    global  ; This word may be omitted if the first line of this function will be something like "local MyVar".
    MyGlobal := 33  ; Assigns 33 to a global variable, first creating the variable if necessary.

    local x, y:=0, z  ; Local variables must be declared in this mode, otherwise they would be assumed global.

}

This assume-global mode can also be used by a function to create a global array, such as a loop that assigns values to Array%A_Index%.
Super-global variables [v1.1.05+]: If a global declaration appears outside of any function, it takes effect for all functions by default
(excluding force-local functions). This avoids the need to redeclare the variable in each function. However, if a function parameter or
local variable with the same name is declared, it takes precedence over the global variable. Variables created by the class keyword are
also super-global.

Static variables


Static variables are always implicitly local, but differ from locals because their values are remembered between calls. For example:

LogToFile(TextToLog)

{

    static LoggedLines = 0

    LoggedLines += 1  ; Maintain a tally locally (its value is remembered between calls).
    global LogFileName

    FileAppend, %LoggedLines%: %TextToLog%`n, %LogFileName%

}

Static Initializers: In versions prior to 1.0.46, all static variables started off blank; so the only way to detect that one was being used for the first time was to check whether it was blank. [v1.0.46+]: A static variable may be initialized to something other than "" by following it with := or = followed by one of the following: true, false, a literal integer, a literal floating point number, or a literal/quoted string
such as "fox". For example: static X:=0, Y:="fox". Each static variable is initialized only once (before the script begins executing).

[AHK_L 58+]: Static var := expression is supported. All such expressions are evaluated immediately before the script's auto-
execute section in the order they are encountered in the script.

Assume-static mode [v1.0.48+]: A function may be defined to assume that all its variables are static (except its parameters) by making its first line the word "static". For example:

GetFromStaticArray(WhichItemNumber)

{

    static

    static FirstCallToUs := true  ; A static declaration's initializer still runs only once (upon startup).
    if FirstCallToUs  ; Create a static array during the first call, but not on subsequent calls.

    {

        FirstCallToUs := false

        Loop 10

            StaticArray%A_Index% := "Value #" . A_Index

    }

    return StaticArray%WhichItemNumber%

}

In assume-static mode, any variable that should not be static must be declared as local or global (with the same exceptions as for assume- local mode, unless force-local mode is also in effect).

[v1.1.27+]: Force-local mode can be combined with assume-static mode by specifying local and then static, as shown below. This
allows the function to use force-local rules but create variables as static by default.

global MyVar := "This is global"
DemonstrateForceStatic()

DemonstrateForceStatic()

{

    local

    static

    MyVar := "This is static"
    ListVars

    MsgBox

}

More about locals and globals

Multiple variables may be declared on the same line by separating them with commas as in these examples:

global LogFileName, MaxRetries := 5
static TotalAttempts = 0, PrevResult

[v1.0.46+]: A local or global variable may be initialized on the same line as its declaration by following it with := or = followed by any expression (the = operator behaves the same as := in declarations). Unlike static initializers, the initializers of locals and globals execute every time the function is called, but only if/when the flow of control actually reaches them. In other words, a line like local x = 0 has the same effect as writing two separate lines: local x followed by x = 0.

Because the words local, global, and static are processed immediately when the script launches, a variable cannot be conditionally
declared by means of an IF statement. In other words, a declaration inside an IF's or ELSE's block takes effect unconditionally for all
lines between the declaration and the function's closing brace. Also note that it is not currently possible to declare a dynamic variable
such as global Array%i%.

For commands that create pseudo-arrays (such as StringSplit), each variable in the resulting pseudo-array is local if the assume-global
mode is not in effect or if the pseudo-array's first element has been declared as a local variable (this is also true if one of the function's
parameters is passed -- even if that parameter is ByRef -- because parameters are similar to local variables). Conversely, if the first

element has been declared global, a global array is created. However, the common source of confusion below applies even in these cases. The first element for StringSplit is ArrayName0. For other array-creating commands such as WinGet List, the first element is

ArrayName (i.e. without the number). [v1.1.27+]: When force-local mode is in effect, these commands follow rules consistent with
normal variable references; that is, any pseudo-array element not declared as global will be local even if other elements are declared
global.


Within a function (unless force-local mode is in effect), any dynamic variable reference such as Array%i% always resolves to a local
variable unless no variable of that name exists, in which case a global is used if it exists. If neither exists and the usage requires the
variable to be created, it is created as a local variable unless the assume-global mode is in effect. Consequently, a function can create a
global array manually (by means such as Array%i% := A_Index) only if it has been defined as an assume-global function.

Common source of confusion: Any non-dynamic reference to a variable creates that variable the moment the script launches. For
example, when used outside a function, MsgBox %Array1% creates Array1 as a global the moment the script launches. Conversely, when used inside a function MsgBox %Array1% creates Array1 as one of the function's locals the moment the script launches (unless assume-
global is in effect), even if Array and Array0 are declared global.

Dynamically Calling a Function

[v1.0.47.06+]: A function (even a built-in function) may be called dynamically via percent signs. For example, %Var%(x, "fox") would call the function whose name is contained in Var. Similarly, Func%A_Index%() would call Func1() or Func2(), etc., depending on the
current value of A_Index.

[v1.1.07.00+]: Var in %Var%() can contain a function name or a function object. If the function does not exist, the default base object's
__Call meta-function is invoked instead.

If the function cannot be called due to one of the reasons below, the evaluation of the expression containing the call stops silently and
prematurely, which may lead to inconsistent results:

Calling a nonexistent function, which can be avoided by using If IsFunc(VarContainingFuncName). Except for built-in
functions, the called function's definition must exist explicitly in the script by means such as #Include or a non-dynamic call to a
library function.

Passing too few parameters, which can be avoided by checking IsFunc()'s return value (which is the number of mandatory
parameters plus one). [v1.0.48+]: Note that passing too many parameters is tolerated; each extra parameter is fully evaluated
(including any calls to functions) and then discarded.

Finally, a dynamic call to a function is slightly slower than a normal call because normal calls are resolved (looked up) before the script
begins running.

Short-circuit Boolean Evaluation

When AND, OR, and the ternary operator are used within an expression, they short-circuit to enhance performance (regardless of whether any function calls are present). Short-circuiting operates by refusing to evaluate parts of an expression that cannot possibly affect its final result. To illustrate the concept, consider this example:

if (ColorName <> "" AND not FindColor(ColorName))
    MsgBox %ColorName% could not be found.

In the example above, the FindColor() function never gets called if the ColorName variable is empty. This is because the left side of the AND would be false, and thus its right side would be incapable of making the final outcome true.

Because of this behavior, it's important to realize that any side-effects produced by a function (such as altering a global variable's
contents) might never occur if that function is called on the right side of an AND or OR.

It should also be noted that short-circuit evaluation cascades into nested ANDs and ORs. For example, in the following expression, only
the leftmost comparison occurs whenever ColorName is blank. This is because the left side would then be enough to determine the final answer with certainty:

if (ColorName = "" OR FindColor(ColorName, Region1) OR FindColor(ColorName, Region2))
    break   ; Nothing to search for, or a match was found.

As shown by the examples above, any expensive (time-consuming) functions should generally be called on the right side of an AND or
OR to enhance performance. This technique can also be used to prevent a function from being called when one of its parameters would be passed a value it considers inappropriate, such as an empty string.

[v1.0.46+]: The ternary conditional operator (?:) also short-circuits by not evaluating the losing branch.
Using Subroutines Within a Function

Although a function cannot contain definitions of other functions, it can contain subroutines. As with other subroutines, use Gosub to
launch them and Return to return (in which case the Return would belong to the Gosub and not the function).

Known limitation: Currently, the name of each subroutine (label) must be unique among those of the entire script. The program will
notify you upon launch if there are duplicate labels.

If a function uses Gosub to jump to a public subroutine (one that lies outside of the function's braces), all variables outside are global and the function's own local variables are not accessible until the subroutine returns. However, A_ThisFunc will still contain the name of the


function.

Although Goto cannot be used to jump from inside a function to outside, it is possible for a function to Gosub an external/public
subroutine and then do a Goto from there.

Although the use of Goto is generally discouraged, it can be used inside a function to jump to another position within the same function. This can help simplify complex functions that have many points of return, all of which need to do some clean-up prior to returning.

A function may contain externally-called subroutines such as timers, GUI g-labels, and menu items. This is generally done to encapsulate them in a separate file for use with #Include, which prevents them from interfering with the script's auto-execute section. However, the
following limitations apply:

Such subroutines should use only static and global variables (not locals) if their function is ever called normally. This is because a
subroutine thread that interrupts a function-call thread (or vice versa) would be able to change the values of local variables seen by
the interrupted thread. Furthermore, any time a function returns to its caller, all of its local variables are made blank to free their
memory.

Such subroutines should use only global variables (not static variables) as GUI control variables.

When a function is entered by a subroutine thread, any references to dynamic variables made by that thread are treated as globals
(including commands that create arrays).

Return, Exit, and General Remarks

If the flow of execution within a function reaches the function's closing brace prior to encountering a Return, the function ends and
returns a blank value (empty string) to its caller. A blank value is also returned whenever the function explicitly omits Return's
parameter.

When a function uses the Exit command to terminate the current thread, its caller does not receive a return value at all. For example, the statement Var := Add(2, 3) would leave Var unchanged if Add() exits. The same thing happens if a function causes a runtime error
such as running a nonexistent file (when UseErrorLevel is not in effect).

A function may alter the value of ErrorLevel for the purpose of returning an extra value that is easy to remember.

To call a function with one or more blank values (empty strings), use an empty pair of quotes as in this example: FindColor(ColorName, "").

Since calling a function does not start a new thread, any changes made by a function to settings such as SendMode and
SetTitleMatchMode will go into effect for its caller too.

The caller of a function may pass a nonexistent variable or array element to it, which is useful when the function expects the
corresponding parameter to be ByRef. For example, calling GetNextLine(BlankArray%i%) would create the variable BlankArray%i%
automatically as a local or global (depending on whether the caller is inside a function and whether it has the assume-global mode in
effect).

When used inside a function, ListVars displays a function's local variables along with their contents. This can help debug a script.
Style and Naming Conventions

You might find that complex functions are more readable and maintainable if their special variables are given a distinct prefix. For
example, naming each parameter in a function's parameter list with a leading "p" or "p_" makes their special nature easy to discern at a
glance, especially when a function has several dozen local variables competing for your attention. Similarly, the prefix "r" or "r_" could be used for ByRef parameters, and "s" or "s_" could be used for static variables.

The One True Brace (OTB) style may optionally be used to define functions. For example:

Add(x, y) {
    return x + y

}

Using #Include to Share Functions Among Multiple Scripts

The #Include directive may be used (even at the top of a script) to load functions from an external file.

Explanation: When the script's flow of execution encounters a function definition, it jumps over it (using an instantaneous method) and
resumes execution at the line after its closing brace. Consequently, execution can never fall into a function from above, nor does the
presence of one or more functions at the very top of a script affect the auto-execute section.

Libraries of Functions: Standard Library and User Library [v1.0.47+]

A script may call a function in an external file without having to use #Include. For this to work, a file of the same name as the function


must exist in one of the following library directories:

%A_ScriptDir%\Lib\  ; Local library - requires [AHK_L 42+].
%A_MyDocuments%\AutoHotkey\Lib\  ; User library.
directory-of-the-currently-running-AutoHotkey.exe\Lib\  ; Standard library.

For example, if a script calls a nonexistent function MyFunc(), the program searches for a file named "MyFunc.ahk" in the user library. If not found there, it searches for it in the standard library. If a match is still not found and the function's name contains an underscore (e.g. MyPrefix_MyFunc), the program searches both libraries for a file named MyPrefix.ahk and loads it if it exists. This allows
MyPrefix.ahk to contain both the function MyPrefix_MyFunc and other related functions whose names start with MyPrefix_.

[AHK_L 42+]: The local library is supported and is searched before the user library and standard library.

Only a direct function call such as MyFunc() can cause a library to be auto-included. If the function is only called dynamically or
indirectly, such as by a timer or GUI event, the library must be explicitly included in the script. For example: #Include <MyFunc>

Although a library file generally contains only a single function of the same name as its filename, it may also contain private functions
and subroutines that are called only by it. However, such functions should have fairly distinct names because they will still be in the
global namespace; that is, they will be callable from anywhere in the script.

If a library file uses #Include, the working directory for #Include is the library file's own directory. This can be used to create a redirect to a larger library file that contains that function and others related to it.

The script compiler (ahk2exe) also supports library functions. However, it requires that a copy of AutoHotkey.exe exist in the directory above the compiler directory (which is normally the case). If AutoHotkey.exe is absent, the compiler still works but library functions are not automatically included.

Functions included from a library perform just as well as other functions because they are pre-loaded before the script begins executing. Built-in Functions

Any optional parameters at the end of a built-in function's parameter list may be completely omitted. For example, WinExist("Untitled - Notepad") is valid because its other three parameters would be considered blank.

A built-in function is overridden if the script defines its own function of the same name. For example, a script could have its own custom WinExist() function that is called instead of the standard one. However, the script would then have no way to call the original function.

External functions that reside in DLL files may be called with DllCall().

To get more details about a particular built-in function below, simply click on its name.
Frequently-used Functions

Function                                                                                           Description
FileExist                        Checks for the existence of a file or folder and returns its attributes.
GetKeyState                  Returns true (1) if the specified key is down and false (0) if it is up.

InStr                              Searches for a given occurrence of a string, from the left or the right.

RegExMatch                 Determines whether a string contains a pattern (regular expression).

RegExReplace               Replaces occurrences of a pattern (regular expression) inside a string.

StrLen                            Retrieves the count of how many characters are in a string.

StrReplace                     Replaces occurrences of the specified substring with a new string.

StrSplit                          Separates a string into an array of substrings using the specified delimiters.

SubStr                            Retrieves one or more characters from the specified position in a string.

WinActive                     Checks if the specified window exists and is currently active (foremost), and returns its Unique ID (HWND).
WinExist                        Checks if a matching window exists and returns the Unique ID (HWND) of the first matching window.

Miscellaneous Functions

Function                                                                                             Description
Asc                                Returns the numeric value of the first byte or UTF-16 code unit in the specified string.

Chr


 

Func                               Retrieves a reference to the specified function.

GetKeyName/VK/SCRetrieves the name/text, virtual key code or scan code of a key.

IsByRef                         Returns a non-zero number if a ByRef parameter of a function was supplied with the specified variable.
IsFunc                            Returns a non-zero number if the specified function exists in the script.

IsLabel                           Returns a non-zero number if the specified label exists in the script.

IsObject                         Returns a non-zero number if the specified value is an object.

ListView                        Functions to add, insert, modify or delete ListView rows/colums, or to get data from them.
NumGet                         Returns the binary number stored at the specified address+offset.

NumPut                         Stores a number in binary format at the specified address+offset.

OnMessage                    Monitors a message/event.

Ord                                Returns the ordinal value (numeric character code) of the first character in the specified string.
StrGet                            Copies a string from a memory address, optionally converting it between code pages.
StrPut                            Copies a string to a memory address, optionally converting it between code pages.
RegisterCallback           Creates a machine-code address that when called, redirects the call to a function in the script.
TreeView                       Functions to add, modify or delete TreeView items, or to get data from them.
Trim                               Trims characters from the beginning and/or end of a string.

VarSetCapacity             Enlarges a variable's holding capacity or frees its memory.

Math

Function                                                                   Description

Abs                                Returns the absolute value of Number.

Ceil                                Returns Number rounded up to the nearest integer (without any .00 suffix).
Exp                                Returns e (which is approximately 2.71828182845905) raised to the Nth power.
Floor                              Returns Number rounded down to the nearest integer (without any .00 suffix).
Log                                Returns the logarithm (base 10) of Number.

Ln                                  Returns the natural logarithm (base e) of Number.

Max / Min                      Returns the highest/lowest value of one or more numbers.
Mod                               Returns the remainder when Dividend is divided by Divisor.
Round                            Returns Number rounded to N decimal places.

Sqrt                                Returns the square root of Number.

Sin / Cos / Tan               Returns the trigonometric sine/cosine/tangent of Number.

ASin / ACos / ATanReturns the arcsine/arccosine/arctangent in radians.

Other Functions

Polyethene's Command Functions: Provides a callable function for each AutoHotkey command that has an OutputVar. This library can be included in any script via #Include.


Advanced Hotkey Features

Table of Contents

General

Remap easy to reach but rarely used keys

Use any keys as modifiers

Make the mouse wheel perform alt-tabbing

Make a keyboard key become a mouse button
Make your hotkeys context-sensitive

Define abbreviations that expand as you type them

Gaming

Reduce wear and tear on your fingers
Create mouse hotkeys

Create "pass-through" hotkeys
Automate game actions on the screen
Use the keyboard hook

Related Topics
General

Remap easy to reach but rarely used keys

Some of the easiest keys to reach on the keyboard are also the least frequently used. Make these keys do something useful! For example, if you rarely use the right Alt key, make it perform the action you do most often:

RAlt::

MsgBox You pressed the right ALT key.
return

You can even do the above without losing the native function of the right Alt key by assigning the right Alt key to be a "prefix" for at
least one other hotkey. In the below example, the right Alt has become a prefix, which automatically allows it to modify all other keys as it normally would. But if you press and release the right Alt key without having used it to modify another key, its hotkey action (above) will take effect immediately:

RAlt & j::AltTab

Use any keys as modifiers

Don't be limited to using only Ctrl, Alt, Shift, and Win as modifiers; you can combine any two keys or mouse buttons to form a custom hotkey. For example: Hold down Numpad0 and press Numpad1 to launch a hotkey (Numpad0 & Numpad1::); hold down CapsLock and
press another key, or click a mouse button (CapsLock & RButton::). In this case, the CapsLock key's state (on or off) is not changed
when it is used to launch the hotkey. For details, see custom combinations of keys.

Make the mouse wheel perform alt-tabbing

Convert the mouse wheel (or any other keys of your choice) into a complete substitute for Alt-Tab. Click the wheel to show or hide the
menu, and turn it to navigate through the menu. The wheel will still function normally whenever the Alt-Tab menu isn't visible. Syntax:

MButton::AltTabMenu
WheelDown::AltTab
WheelUp::ShiftAltTab

Make a keyboard key become a mouse button

Make a keyboard key become a mouse button, or have an action repeated continuously while you're holding down a key or mouse
button. See the remapping page for examples.

Make your hotkeys context-sensitive

Have your easiest-to-reach hotkeys perform an action appropriate to the type of window you're working with. In the following example, the right Ctrl key performs a different action depending on whether Notepad or Calculator is the active window:

#IfWinActive ahk_class Notepad

RControl::WinMenuSelectItem, , , File, Save  ; Save the current file in Notepad.

#IfWinActive Calculator

RControl::Send, ^c!{tab}^v  ; Copy the Calculator's result into the previously active window.

See #IfWinActive for details.


Define abbreviations that expand as you type them

Also known as hotstrings. No special training or scripting experience is needed. For example, a script containing the following lines
would expand ceo, cfo, and btw wherever you type them:

::ceo::Chief Executive Officer
::cfo::Chief Financial Officer
::btw::by the way

Gaming

Reduce wear and tear on your fingers

Reduce wear and tear on your fingers by using virtually any key as a hotkey, including single letters, arrow keys, Numpad keys, and even the modifier keys themselves (Ctrl/Alt/Win/Shift).

Create mouse hotkeys

Create mouse hotkeys, including the mouse wheel button (MButton) and the turning of the wheel up/down or left/right (WheelUp,
WheelDown, WheelLeft, and WheelRight). You can also combine a keyboard key with a mouse button. For example, control-right-
button would be expressed as ^RButton::.

Create "pass-through" hotkeys

For example, the left mouse button can trigger a hotkey action even while the click itself is being sent into the game normally (syntax:
~LButton::).

Automate game actions on the screen

Use commands such as PixelSearch, PixelGetColor, and ImageSearch to automate game actions.
Use the keyboard hook

Have the option of using the keyboard hook to implement hotkeys, which might be more responsive than other hotkey methods while the CPU is under load in a game. The hook might also be able to override any restrictions a game may have about which keys can be
"mapped" to game actions.

Related Topics

Hotkeys
Hotstrings
Remapping Keys


Hotkeys (Mouse, Joystick and Keyboard Shortcuts)

Table of Contents

Introduction and Simple Examples
Hotkey Modifier Symbols
Context-sensitive Hotkeys

Custom Combinations

Other Features

Mouse Wheel Hotkeys

Hotkey Tips and Remarks

Alt-Tab Hotkeys

Function Hotkeys [v1.1.20+]

Introduction and Simple Examples

Hotkeys are sometimes referred to as shortcut keys because of their ability to easily trigger an action (such as launching a program or keyboard macro). In the
following example, the hotkey Win+N is configured to launch Notepad. The pound sign [#] stands for the Win key, which is known as a modifier:

#n::

Run Notepad
return

In the final line above, return serves to finish the hotkey. However, if a hotkey needs to execute only a single line, that line can be listed to the right of the double- colon. In other words, the return is implicit:

#n::Run Notepad

To use more than one modifier with a hotkey, list them consecutively (the order does not matter). The following example uses ^!s to indicate Control+Alt+S:

^!s::

Send Sincerely,{enter}John Smith  ; This line sends keystrokes to the active (foremost) window.
return

Hotkey Modifier Symbols

You can use the following modifier symbols to define hotkeys:

Symbol                                                                                                                                 Description

Win (Windows logo key).

[v1.0.48.01+]: For Windows Vista and later, hotkeys that include the Win key (e.g. #a) will wait for the Win key to be released before sending any text


#


containing an L keystroke. This prevents usages of Send within such a hotkey from locking the PC. This behavior applies to all sending modes except SendPlay (which doesn't need it) and blind mode. [v1.1.29+]: Text mode is also excluded.

Note: Pressing a hotkey which includes the Win key may result in extra simulated keystrokes (Ctrl by default). See #MenuMaskKey.


 

Alt

Note: Pressing a hotkey which includes the Alt key may result in extra simulated keystrokes (Ctrl by default). See #MenuMaskKey.

^              Control

+             Shift

&            An ampersand may be used between any two keys or mouse buttons to combine them into a custom hotkey. See below for details.
<             Use the left key of the pair. e.g. <!a is the same as !a except that only the left Alt key will trigger it.

>             Use the right key of the pair.

AltGr (alternate graving). If your keyboard layout has AltGr instead of a right Alt key, this series of symbols can usually be used to stand for AltGr. For example:

<^>!m::MsgBox You pressed AltGr+m.


<^>!

 

 

 

 

 

*


<^<!m::MsgBox You pressed LeftControl+LeftAlt+m.

Alternatively, to make AltGr itself into a hotkey, use the following hotkey (without any hotkeys like the above present):

LControl & RAlt::MsgBox You pressed AltGr itself.

 

Wildcard: Fire the hotkey even if extra modifiers are being held down. This is often used in conjunction with remapping keys or buttons. For example:

*#c::Run Calc.exe  ; Win+C, Shift+Win+C, Ctrl+Win+C, etc. will all trigger this hotkey.

*ScrollLock::Run Notepad  ; Pressing ScrollLock will trigger this hotkey even when modifier key(s) are down.

Wildcard hotkeys always use the keyboard hook, as do any hotkeys eclipsed by a wildcard hotkey. For example, the presence of *a:: would cause ^a:: to always use the hook.


 

 

 

 

 

 

 

 

~

 

 

 

 

 

 

 

 

 

 

 

$

 

 

 

 

 

 

 

 

 

UP


When the hotkey fires, its key's native function will not be blocked (hidden from the system). In both of the below examples, the user's click of the mouse button will be sent to the active window:

~RButton::MsgBox You clicked the right mouse button.

~RButton & C::MsgBox You pressed C while holding down the right mouse button.

Unlike the other prefix symbols, the tilde prefix is allowed to be present on some of a hotkey's variants but absent on others. However, if a tilde is applied to the prefix key of any custom combination which has not been turned off or suspended, it affects the behavior of that prefix key for all combinations.

Special hotkeys that are substitutes for alt-tab always ignore the tilde prefix.

[v1.1.14+]: If the tilde prefix is applied to a custom modifier key (prefix key) which is also used as its own hotkey, that hotkey will fire when the key is
pressed instead of being delayed until the key is released. For example, the ~RButton hotkey above is fired as soon as the button is pressed. Prior to
[v1.1.14] (or without the tilde prefix), it was fired when the button was released, but only if the RButton & C combination was not activated.

If the tilde prefix is applied only to the custom combination and not the non-combination hotkey, the key's native function will still be blocked. For
example, in the script below, holding Menu will show the ToolTip and will not trigger a context menu:

AppsKey::ToolTip Press < or > to cycle through windows.
AppsKey Up::ToolTip

~AppsKey & <::Send !+{Esc}

~AppsKey & >::Send !{Esc}

If at least one variant of a keyboard hotkey has the tilde modifier, that hotkey always uses the keyboard hook.

 

This is usually only necessary if the script uses the Send command to send the keys that comprise the hotkey itself, which might otherwise cause it to
trigger itself. The $ prefix forces the keyboard hook to be used to implement this hotkey, which as a side-effect prevents the Send command from triggering it. The $ prefix is equivalent to having specified #UseHook somewhere above the definition of this hotkey.

The $ prefix has no effect for mouse hotkeys, since they always use the mouse hook. It also has no effect for hotkeys which already require the keyboard
hook, including any keyboard hotkeys with the tilde (~) or wildcard (*) modifiers, key-up hotkeys and custom combinations. To determine whether a
particular hotkey uses the keyboard hook, use ListHotkeys.

[v1.1.06+]: #InputLevel and SendLevel provide additional control over which hotkeys and hotstrings are triggered by the Send command.

 

The word UP may follow the name of a hotkey to cause the hotkey to fire upon release of the key rather than when the key is pressed down. The following example remaps the left Win key to become the left Control key:

*LWin::Send {LControl down}
*LWin Up::Send {LControl up}

"Up" can also be used with normal hotkeys as in this example: ^!r Up::MsgBox You pressed and released Ctrl+Alt+R. It also works with
combination hotkeys (e.g. F1 & e Up::)

Limitations: 1) "Up" does not work with joystick buttons; and 2) An "Up" hotkey without a normal/down counterpart hotkey will completely take over that key to prevent it from getting stuck down. One way to prevent this is to add a tilde prefix (e.g. ~LControl up::)

"Up" hotkeys and their key-down counterparts (if any) always use the keyboard hook.

On a related note, a technique similar to the above is to make a hotkey into a prefix key. The advantage is that although the hotkey will fire upon release, it will do so only if you did not press any other key while it was held down. For example:

LControl & F1::return  ; Make left-control a prefix by using it in front of "&" at least once.
LControl::MsgBox You released LControl without having used it to modify any other key.


 

Note: See the Key List for a complete list of keyboard keys and mouse/joystick buttons.

 

Multiple hotkeys can be stacked vertically to have them perform the same action. For example:

^Numpad0::
^Numpad1::
MsgBox Pressing either Control+Numpad0 or Control+Numpad1 will display this message.

return

A key or key-combination can be disabled for the entire system by having it do nothing. The following example disables the right-side Win key:

RWin::return
Context-sensitive Hotkeys

The directives #IfWinActive/Exist and #If can be used to make a hotkey perform a different action (or none at all) depending on a specific condition. For example:

#IfWinActive, ahk_class Notepad

^a::MsgBox You pressed Ctrl-A while Notepad is active. Pressing Ctrl-A in any other window will pass the Ctrl-A keystroke to that window. #c::MsgBox You pressed Win-C while Notepad is active.

#IfWinActive

#c::MsgBox You pressed Win-C while any window except Notepad is active.

#If MouseIsOver("ahk_class Shell_TrayWnd")

WheelUp::Send {Volume_Up}     ; Wheel over taskbar: increase/decrease volume.
WheelDown::Send {Volume_Down} ;

Custom Combinations


You can define a custom combination of two keys (except joystick buttons) by using " & " between them. In the below example, you would hold down Numpad0
then press the second key to trigger the hotkey:

Numpad0 & Numpad1::MsgBox You pressed Numpad1 while holding down Numpad0.
Numpad0 & Numpad2::Run Notepad

The prefix key loses its native function: In the above example, Numpad0 becomes a prefix key; but this also causes Numpad0 to lose its original/native function
when it is pressed by itself. To avoid this, a script may configure Numpad0 to perform a new action such as one of the following:

Numpad0::WinMaximize A   ; Maximize the active/foreground window.

Numpad0::Send {Numpad0}  ; Make the release of Numpad0 produce a Numpad0 keystroke. See comment below.

Fire on release: The presence of one of the above custom combination hotkeys causes the release of Numpad0 to perform the indicated action, but only if you did
not press any other keys while Numpad0 was being held down. [v1.1.14+]: This behaviour can be avoided by applying the tilde prefix to either hotkey.

Modifiers: Unlike a normal hotkey, custom combinations act as though they have the wildcard (*) modifier by default. For example, 1 & 2:: will activate even if
Ctrl or Alt is held down when 1 and 2 are pressed, whereas ^1:: would be activated only by Ctrl+1 and not Ctrl+Alt+1.

For standard modifier keys, normal hotkeys typically work as well or better than "custom" combinations. For example, <+s:: is recommended over LShift & s::. Combinations of three or more keys are not supported. Combinations which your keyboard hardware supports can usually be detected by using #If and GetKeyState, but the results may be inconsistent. For example:

; Press AppsKey and Alt in any order, then slash (/).
#if GetKeyState("AppsKey", "P")

Alt & /::MsgBox Hotkey activated.

; If the keys are swapped, Alt must be pressed first (use one at a time):
#if GetKeyState("Alt", "P")

AppsKey & /::MsgBox Hotkey activated.

; [ & ] & \::

#if GetKeyState("[") && GetKeyState("]")
\::MsgBox

Keyboard hook: Custom combinations involving keyboard keys always use the keyboard hook, as do any hotkeys which use the prefix key as a suffix. For example, a & b:: causes ^a:: to always use the hook.

Other Features

NumLock, CapsLock, and ScrollLock: These keys may be forced to be "AlwaysOn" or "AlwaysOff". For example: SetNumLockState AlwaysOn.

Overriding Explorer's hotkeys: Windows' built-in hotkeys such as Win+E (#e) and Win+R (#r) can be individually overridden simply by assigning them to an action in the script. See the override page for details.

Substitutes for Alt-Tab: Hotkeys can provide an alternate means of alt-tabbing. For example, the following two hotkeys allow you to alt-tab with your right hand:

RControl & RShift::AltTab  ; Hold down right-control then press right-shift repeatedly to move forward.

RControl & Enter::ShiftAltTab  ; Without even having to release right-control, press Enter to reverse direction.

For more details, see Alt-Tab.
Mouse Wheel Hotkeys

Hotkeys that fire upon turning the mouse wheel are supported via the key names WheelDown and WheelUp. [v1.0.48+]: WheelLeft and WheelRight are also
supported, but have no effect on operating systems older than Windows Vista. Here are some examples of mouse wheel hotkeys:

MButton & WheelDown::MsgBox You turned the mouse wheel down while holding down the middle button.
^!WheelUp::MsgBox You rotated the wheel up while holding down Control+Alt.

[v1.0.43.03+]: The built-in variable A_EventInfo contains the amount by which the wheel was turned, which is typically 1. However, A_EventInfo can be greater or less than 1 under the following circumstances:

If the mouse hardware reports distances of less than one notch, A_EventInfo may contain 0;

If the wheel is being turned quickly (depending on type of mouse), A_EventInfo may be greater than 1. A hotkey like the following can help analyze your
mouse: ~WheelDown::ToolTip %A_EventInfo%.

Some of the most useful hotkeys for the mouse wheel involve alternate modes of scrolling a window's text. For example, the following pair of hotkeys scrolls
horizontally instead of vertically when you turn the wheel while holding down the left Control key:

~LControl & WheelUp::  ; Scroll left.

ControlGetFocus, fcontrol, A

Loop 2  ; <-- Increase this value to scroll faster.

    SendMessage, 0x114, 0, 0, %fcontrol%, A  ; 0x114 is WM_HSCROLL and the 0 after it is SB_LINELEFT.
return

~LControl & WheelDown::  ; Scroll right.

ControlGetFocus, fcontrol, A

Loop 2  ; <-- Increase this value to scroll faster.

    SendMessage, 0x114, 1, 0, %fcontrol%, A  ; 0x114 is WM_HSCROLL and the 1 after it is SB_LINERIGHT.
return

Finally, since mouse wheel hotkeys generate only down-events (never up-events), they cannot be used as key-up hotkeys.
Hotkey Tips and Remarks

Each numpad key can be made to launch two different hotkey subroutines depending on the state of NumLock. Alternatively, a numpad key can be made to launch the same subroutine regardless of the NumLock state. For example:

NumpadEnd::
Numpad1::


MsgBox, This hotkey is launched regardless of whether NumLock is on.
return

If the tilde (~) operator is used with a prefix key even once, it changes the behavior of that prefix key for all combinations. For example, in both of the below
hotkeys, the active window will receive all right-clicks even though only one of the definitions contains a tilde:

~RButton & LButton::MsgBox You pressed the left mouse button while holding down the right.
RButton & WheelUp::MsgBox You turned the mouse wheel up while holding down the right button.

The Suspend command can temporarily disable all hotkeys except for ones you make exempt. For greater selectivity, use #IfWinActive/Exist.

By means of the Hotkey command, hotkeys can be created dynamically while the script is running. The Hotkey command can also modify, disable, or enable the
script's existing hotkeys individually.

Joystick hotkeys do not currently support modifier prefixes such as ^ (Control) and # (Win). However, you can use GetKeyState to mimic this effect as shown in the following example:

Joy2::

if not GetKeyState("Control")  ; Neither the left nor right Control key is down.
    return  ; i.e. Do nothing.

MsgBox You pressed the first joystick's second button while holding down the Control key.
return

There may be times when a hotkey should wait for its own modifier keys to be released before continuing. Consider the following example:

^!s::Send {Delete}

Pressing Control+Alt+S would cause the system to behave as though you pressed Control+Alt+Delete (due to the system's aggressive detection of
Ctrl+Alt+Delete). To work around this, use KeyWait to wait for the keys to be released; for example:

^!s::

KeyWait Control
KeyWait Alt
Send {Delete}
return

If a hotkey label like #z:: produces an error like "Invalid Hotkey", your system's keyboard layout/language might not have the specified character ("Z" in this case). Try using a different character that you know exists in your keyboard layout.

A hotkey label can be used as the target of a Gosub or Goto. For example: Gosub ^!s.

One common use for hotkeys is to start and stop a repeating action, such as a series of keystrokes or mouse clicks. For an example of this, see this FAQ topic.
Finally, each script is quasi multi-threaded, which allows a new hotkey to be launched even when a previous hotkey subroutine is still running. For example, new
hotkeys can be launched even while a MsgBox is being displayed by the current hotkey.

Alt-Tab Hotkeys

Each Alt-Tab hotkey must be a combination of two keys, which is typically achieved via the ampersand symbol (&). In the following example, you would hold
down the right Alt key and press J or K to navigate the alt-tab menu:

RAlt & j::AltTab

RAlt & k::ShiftAltTab

AltTab and ShiftAltTab are two of the special commands that are only recognized when used on the same line as a hotkey. Here is the complete list:

AltTab: If the alt-tab menu is visible, move forward in it. Otherwise, display the menu (only if the hotkey is an "&" combination of two keys; otherwise, it does
nothing).

ShiftAltTab: Same as above except move backward in the menu.

AltTabAndMenu: If the alt-tab menu is visible, move forward in it. Otherwise, display the menu.

AltTabMenuDismiss: Close the Alt-tab menu.

To illustrate the above, the mouse wheel can be made into an entire substitute for Alt-tab. With the following hotkeys in effect, clicking the middle button displays
the menu and turning the wheel navigates through it:

MButton::AltTabMenu
WheelDown::AltTab
WheelUp::ShiftAltTab

To cancel a hotkey-invoked Alt-tab menu without activating the selected window, use a hotkey such as the following. It might require adjustment depending on: 1) the means by which the alt-tab menu was originally displayed; and 2) whether the script has the keyboard hook installed.

LCtrl & CapsLock::AltTab

!MButton::  ; Middle mouse button. The ! prefix makes it fire while the Alt key is down (which it is if the alt-tab menu is visible).
IfWinExist ahk_class #32771  ; Indicates that the alt-tab menu is present on the screen.

    Send !{Escape}{Alt up}

return

Currently, all special Alt-tab actions must be assigned directly to a hotkey as in the examples above (i.e. they cannot be used as though they were commands). They are not affected by #IfWin or #If.

Custom alt-tab actions can also be created via hotkeys. In the following example, you would press F1 to display the menu and advance forward in it. Then you would press F2 to activate the selected window (or press Escape to cancel):

*F1::Send {Alt down}{tab} ; Asterisk is required in this case.

!F2::Send {Alt up}  ; Release the Alt key, which activates the selected window.
~*Escape::

IfWinExist ahk_class #32771

    Send {Escape}{Alt up}  ; Cancel the menu without activating the selected window.
return


Function Hotkeys [v1.1.20+]

One or more hotkeys can be assigned a function by simply defining it immediately after the hotkey label as in this example:

; Ctrl+Shift+O to open containing folder in Explorer.

; Ctrl+Shift+E to open folder with current file selected.

; Supports SciTE and Notepad++.

^+o::

^+e::

    editor_open_folder() {

        WinGetTitle, path, A

        if RegExMatch(path, "\*?\K(.*)\\[^\\]+(?= [-*] )", path)
            if (FileExist(path) && A_ThisHotkey = "^+e")
                Run explorer.exe /select`,"%path%"
            else

                Run explorer.exe "%path1%"

    }

[v1.1.28+]: Hotstrings can also be defined this way. Multiple hotkeys or hotstrings can be stacked together to call the same function.

There must only be whitespace, comments or directives between the hotkey/hotstring labels or label and the function. Hotkey/hotstring labels defined this way are not visible to IsLabel, Gosub or other commands; however, the auto-execute section ends at the first hotkey/hotstring even if it is assigned a function.

The main benefit of using a function is that local variables can be used, which avoids conflicts when two or more hotkeys use the same variable names for different purposes. It also encourages self-documenting hotkeys, like in the code above where the function name describes the hotkey.

The Hotkey command can also be used to assign a function or function object to a hotkey.


Hotstrings

Table of Contents

Introduction and Simple Examples
Ending Characters

Options

Long Replacements
Context-sensitive Hotstrings
AutoCorrect

Remarks

Function Hotstrings [v1.1.28+]
Hotstring Helper

Introduction and Simple Examples

Although hotstrings are mainly used to expand abbreviations as you type them (auto-replace), they can also be used to launch any scripted action. In this respect, they are similar to hotkeys except that they are typically
composed of more than one character (that is, a string).

To define a hotstring, enclose the triggering abbreviation between pairs of colons as in this example:

::btw::by the way

In the above example, the abbreviation btw will be automatically replaced with "by the way" whenever you type it (however, by default you must type an ending character after typing btw, such as Space, ., or Enter).
The "by the way" example above is known as an auto-replace hotstring because the typed text is automatically erased and replaced by the string specified after the second pair of colons. By contrast, a hotstring may also be defined to perform any custom action as in the following examples. Note that the commands must appear beneath the hotstring:

::btw::

MsgBox You typed "btw".
return

:*:]d::  ; This hotstring replaces "]d" with the current date and time via the commands below.
FormatTime, CurrentDateTime,, M/d/yyyy h:mm tt  ; It will look like 9/1/2005 3:53 PM

SendInput %CurrentDateTime%

return

Even though the two examples above are not auto-replace hotstrings, the abbreviation you type is erased by default. This is done via automatic backspacing, which can be disabled via the b0 option.
Ending Characters

Unless the asterisk option is in effect, you must type an ending character after a hotstring's abbreviation to trigger it. Ending characters initially consist of the following: -()[]{}':;"/\,.?!`n `t (note that `n is Enter, `t is Tab, and there is a plain space between `n and `t). This set of characters can be changed by editing the following example, which sets the new ending characters for all hotstrings, not just the ones beneath it:

#Hotstring EndChars -()[]{}:;'"/\,.?!`n `t

[v1.1.28+]: The ending characters can be changed while the script is running by calling the Hotstring function as demonstrated below:

Hotstring("EndChars", "-()[]{}:;")
Options

A hotstring's default behavior can be changed in two possible ways:

1. The #Hotstring directive, which affects all hotstrings physically beneath that point in the script. The following example puts the C and R options into effect: #Hotstring c r.

2. Putting options inside a hotstring's first pair of colons. The following example puts the C and * options (case sensitive and "ending character not required") into effect for a single hotstring:
:c*:j@::john@somedomain.com.

The list below describes each option. When specifying more than one option using the methods above, spaces optionally may be included between them.
* (asterisk): An ending character (e.g. Space, ., or Enter) is not required to trigger the hotstring. For example:

:*:j@::jsmith@somedomain.com

The example above would send its replacement the moment you type the @ character. When using the #Hotstring directive, use *0 to turn this option back off.

? (question mark): The hotstring will be triggered even when it is inside another word; that is, when the character typed immediately before it is alphanumeric. For example, if :?:al::airline is a hotstring, typing
"practical " would produce "practicairline ". Use ?0 to turn this option back off.

B0 (B followed by a zero): Automatic backspacing is not done to erase the abbreviation you type. Use a plain B to turn backspacing back on after it was previously turned off. A script may also do its own backspacing via {bs 5}, which sends 5 Backspace keystrokes. Similarly, it may send keystrokes via {left 5}. For example, the following hotstring produces "<em></em>" and moves the caret 5 places to the left (so that it's between the tags):

:*b0:<em>::</em>{left 5}

C: Case sensitive: When you type an abbreviation, it must exactly match the case defined in the script. Use C0 to turn case sensitivity back off.

C1: Do not conform to typed case. Use this option to make auto-replace hotstrings case insensitive and prevent them from conforming to the case of the characters you actually type. Case-conforming hotstrings (which are the default) produce their replacement text in all caps if you type the abbreviation in all caps. If you type the first letter in caps, the first letter of the replacement will also be capitalized (if it is a letter). If you type the case in any other way, the replacement is sent exactly as defined. When using the #Hotstring directive, C0 can be used to turn this option back off, which makes hotstrings conform again.

Kn: Key-delay: This rarely-used option sets the delay between keystrokes produced by auto-backspacing or auto-replacement. Specify the new delay for n; for example, specify k10 to have a 10ms delay and k-1 to have no delay. The exact behavior of this option depends on which sending mode is in effect:

SI (SendInput): Key-delay is ignored because a delay is not possible in this mode. The exception to this is when SendInput is unavailable, in which case hotstrings revert to SendPlay mode below (which does obey
key-delay).

SP (SendPlay): A delay of length zero is the default, which for SendPlay is the same as -1 (no delay). In this mode, the delay is actually a PressDuration rather than a delay between keystrokes.

SE (SendEvent): A delay of length zero is the default. Zero is recommended for most purposes since it is fast but still cooperates well with other processes (due to internally doing a Sleep 0). Specify k-1 to have no
delay at all, which is useful to make auto-replacements faster if your CPU is frequently under heavy load. When set to -1, a script's process-priority becomes an important factor in how fast it can send keystrokes. To
raise a script's priority, use Process, Priority,, High.

O: Omit the ending character of auto-replace hotstrings when the replacement is produced. This is useful when you want a hotstring to be kept unambiguous by still requiring an ending character, but don't actually want the ending character to be shown on the screen. For example, if :o:ar::aristocrat is a hotstring, typing "ar" followed by the spacebar will produce "aristocrat" with no trailing space, which allows you to make the word plural or possessive without having to press Backspace. Use O0 (the letter O followed by a zero) to turn this option back off.

Pn: The priority of the hotstring (e.g. P1). This rarely-used option has no effect on auto-replace hotstrings.

R: Send the replacement text raw; that is, without translating {Enter} to Enter, ^c to Control+C, etc. This option is put into effect automatically for hotstrings that have a continuation section. Use R0 to turn this option back off.

Note: Text mode may be more reliable. The R and T options are mutually exclusive.

SI or SP or SE [v1.0.43+]: Sets the method by which auto-replace hotstrings send their keystrokes. These options are mutually exclusive: only one can be in effect at a time. The following describes each option:

SI stands for SendInput, which typically has superior speed and reliability than the other modes. Another benefit is that like SendPlay below, SendInput postpones anything you type during a hotstring's auto-
replacement text. This prevents your keystrokes from being interspersed with those of the replacement. When SendInput is unavailable, hotstrings automatically use SendPlay instead.

SP stands for SendPlay, which may allow hotstrings to work in a broader variety of games.

SE stands for SendEvent, which is the default in versions older than 1.0.43.

If none of the above options are used, the default mode in [v1.0.43] and later is SendInput. However, unlike the SI option, SendEvent is used instead of SendPlay when SendInput is unavailable.

T [v1.1.27+]: Send the replacement text raw, without translating each character to a keystroke. For details, see Text mode. Use T0 or R0 to turn this option back off, or override it with R.

X [v1.1.28+]: Execute. Instead of replacement text, the hotstring accepts a command or expression to execute. For example, :X:~mb::MsgBox would cause a message box to be displayed when the user types "~mb" instead


of auto-replacing it with the word "MsgBox". This is most useful when defining a large number of hotstrings which call functions, as it would otherwise require three lines per hotstring.

When used with the Hotstring function, the X option causes the Replacement parameter to be interpreted as a label or function name instead of replacement text. However, the X option has this effect only if it is specified each time the function is called.

Z: This rarely-used option resets the hotstring recognizer after each triggering of the hotstring. In other words, the script will begin waiting for an entirely new hotstring, eliminating from consideration anything you
previously typed. This can prevent unwanted triggerings of hotstrings. To illustrate, consider the following hotstring:

:b0*?:11::
SendInput xx
return

Since the above lacks the Z option, typing 111 (three consecutive 1's) would trigger the hotstring twice because the middle 1 is the last character of the first triggering but also the first character of the second triggering. By adding the letter Z in front of b0, you would have to type four 1's instead of three to trigger the hotstring twice. Use Z0 to turn this option back off.

Long Replacements

Hotstrings that produce a large amount of replacement text can be made more readable and maintainable by using a continuation section. For example:

::text1::

(

Any text between the top and bottom parentheses is treated literally, including commas and percent signs.
By default, the hard carriage return (Enter) between the previous line and this one is also preserved.
    By default, the indentation (tab) to the left of this line is preserved.

See continuation section for how to change these default behaviors.

)

The presence of a continuation section also causes the hotstring to default to raw mode. The only way to override this special default is to specify the r0 option in each hotstring that has a continuation section (e.g.
:r0:text1::).

Context-sensitive Hotstrings

The directives #IfWinActive/Exist can be used to make selected hotstrings context sensitive. Such hotstrings send a different replacement, perform a different action, or do nothing at all depending on the type of window that is active or exists. For example:

#IfWinActive ahk_class Notepad

::btw::This replacement text will appear only in Notepad.
#IfWinActive

::btw::This replacement text appears in windows other than Notepad.

AutoCorrect

The following script uses hotstrings to correct about 4700 common English misspellings on-the-fly. It also includes a Win+H hotkey to make it easy to add more misspellings:
Download: AutoCorrect.ahk (127 KB)

Author: Jim Biancolo and Wikipedia's Lists of Common Misspellings

Remarks

Variable references such as %MyVar% are not currently supported within the replacement text. To work around this, don't make such hotstrings auto-replace. Instead, use the SendInput command beneath the abbreviation, followed by a line containing only the word Return.

To send an extra space or tab after a replacement, include the space or tab at the end of the replacement but make the last character an accent/backtick (`). For example:

:*:btw::By the way `

By default, any click of the left or right mouse button will reset the hotstring recognizer. In other words, the script will begin waiting for an entirely new hotstring, eliminating from consideration anything you previously typed (if this is undesirable, specify the line #Hotstring NoMouse anywhere in the script). This "reset upon mouse click" behavior is the default because each click typically moves the text insertion point (caret) or sets
keyboard focus to a new control/field. In such cases, it is usually desirable to: 1) fire a hotstring even if it lacks the question mark option; 2) prevent a firing when something you type after clicking the mouse accidentally forms a valid abbreviation with what you typed before.

The hotstring recognizer checks the active window each time a character is typed, and resets if a different window is active than before. If the active window changes but reverts before any characters are typed, the change is not detected (but the hotstring recognizer may be reset for some other reason). The hotstring recognizer can also be reset by calling Hotstring("Reset").

The built-in variable A_EndChar contains the ending character that you typed to trigger the most recent non-auto-replace hotstring. If no ending character was required (due to the * option), it will be blank. A_EndChar is useful when making hotstrings that use the Send command or whose behavior should vary depending on which ending character you typed. To send the ending character itself, use SendRaw %A_EndChar% (SendRaw is used because characters such as !{} would not be sent correctly by the normal Send command).

Although commas, percent signs, and single-colons within hotstring definitions do not need to be escaped, backticks and those semicolons having a space or tab to their left require it. See escape sequences for a complete list.

Although the Send command's special characters such as {Enter} are supported in auto-replacement text (unless the raw option is used), the hotstring abbreviations themselves do not use this. Instead, specify `n for the
Enter key and `t (or a literal tab) for Tab (see escape sequences for a complete list). For example, the hotstring :*:ab`t:: would be triggered when you type "ab" followed by a tab.

Spaces and tabs are treated literally within hotstring definitions. For example, the following would produce two different results: ::btw::by the way and ::btw:: by the way.

Each hotstring abbreviation can be no more than 40 characters long. The program will warn you if this length is exceeded. By contrast, the length of hotstring's replacement text is limited to about 5000 characters when the sending mode is at its default of SendInput. That limit can be increased to 16,383 characters by switching to one of the other sending modes. Furthermore, an unlimited amount of text can be sent by using SendPlay
%MyVariable% in the body of the hotstring.

The order in which hotstrings are defined determines their precedence with respect to each other. In other words, if more than one hotstring matches something you type, only the one listed first in the script will take effect. Related topic: context-sensitive hotstrings.

Any backspacing you do is taken into account for the purpose of detecting hotstrings. However, the use of , , , , PageUp, PageDown, Home, and End to navigate within an editor will cause the hotstring recognition
process to reset. In other words, it will begin waiting for an entirely new hotstring.

A hotstring may be typed even when the active window is ignoring your keystrokes. In other words, the hotstring will still fire even though the triggering abbreviation is never visible. In addition, you may still press the
Backspace key to undo the most recently typed keystroke (even though you can't see the effect).

It is possible to Gosub or Goto a hotstring label by including its first pair of colons (including any option symbols) in front of its name. For example: Gosub ::xyz. However, jumping to a single-line (auto-replace)
hotstring will do nothing other than execute a return.

Although hotstrings are not monitored and will not be triggered during the course of an invisible Input command, visible Inputs are capable of triggering them.

By default, hotstrings are never triggered by keystrokes produced by any AutoHotkey script. This avoids the possibility of an infinite loop where hotstrings trigger each other over and over. In [v1.1.06] and later, this
behaviour can be controlled with #InputLevel and SendLevel. However, auto-replace hotstrings always use send level 0 and therefore never trigger hook hotkeys or hotstrings.

[v1.1.28+]: Hotstrings can be created dynamically by means of the Hotstring function, which can also modify, disable, or enable the script's existing hotstrings individually.

The Input command is more flexible than hotstrings for certain purposes. For example, it allows your keystrokes to be invisible in the active window (such as a game). It also supports non-character ending keys such as
Escape.

The keyboard hook is automatically used by any script that contains hotstrings.
Hotstrings behave identically to hotkeys in the following ways:

They are affected by the Suspend command.

They obey #MaxThreads and #MaxThreadsPerHotkey (but not #MaxThreadsBuffer).

Scripts containing hotstrings are automatically persistent.

Non-auto-replace hotstrings will create a new thread when launched. In addition, they will update the built-in hotkey variables such as A_ThisHotkey.

Known limitation: On some systems in Java applications, hotstrings might interfere with the user's ability to type diacritical letters (via dead keys). To work around this, Suspend can be turned on temporarily (which
disables all hotstrings).


Function Hotstrings [v1.1.28+]

One or more hotstrings can be assigned a function by simply defining it immediately after the hotstring label, as in this example:

; This example also demonstrates one way to implement case conformity in a script.
:C:BTW::  ; Typed in all-caps.

:C:Btw::  ; Typed with only the first letter upper-case.

: :btw::  ; Typed in any other combination.

    case_conform_btw() {

        hs := A_ThisHotkey  ; For convenience and in case we're interrupted.
        if (hs == ":C:BTW")

            Send BY THE WAY

        else if (hs == ":C:Btw")

            Send By the way

        else

            Send by the way

    }

For additional details, see Function Hotkeys.

The Hotstring function can also be used to assign a function or function object to a hotstring.
Hotstring Helper

Andreas Borutta suggested the following script, which might be useful if you are a heavy user of hotstrings. By pressing Win+H (or another hotkey of your choice), the currently selected text can be turned into a hotstring.
For example, if you have "by the way" selected in a word processor, pressing Win+H will prompt you for its abbreviation (e.g. btw) and then add the new hotstring to the script. It will then reload the script to activate the
hotstring.

Note: The Hotstring function can be used to create new hotstrings without reloading. Take a look at the first example in the example section of the function's page to see how this could be done.

#h::  ; Win+H hotkey

; Get the text currently selected. The clipboard is used instead of

; "ControlGet Selected" because it works in a greater variety of editors

; (namely word processors).  Save the current clipboard contents to be

; restored later. Although this handles only plain text, it seems better

; than nothing:

AutoTrim Off  ; Retain any leading and trailing whitespace on the clipboard.

ClipboardOld = %ClipboardAll%

Clipboard =  ; Must start off blank for detection to work.

Send ^c

ClipWait 1

if ErrorLevel  ; ClipWait timed out.

    return

; Replace CRLF and/or LF with `n for use in a "send-raw" hotstring:

; The same is done for any other characters that might otherwise

; be a problem in raw mode:

StringReplace, Hotstring, Clipboard, ``, ````, All  ; Do this replacement first to avoid interfering with the others below.

StringReplace, Hotstring, Hotstring, `r`n, ``r, All  ; Using `r works better than `n in MS Word, etc.

StringReplace, Hotstring, Hotstring, `n, ``r, All

StringReplace, Hotstring, Hotstring, %A_Tab%, ``t, All

StringReplace, Hotstring, Hotstring, `;, ```;, All

Clipboard = %ClipboardOld%  ; Restore previous contents of clipboard.

; This will move the InputBox's caret to a more friendly position:

SetTimer, MoveCaret, 10

; Show the InputBox, providing the default hotstring:

InputBox, Hotstring, New Hotstring, Type your abreviation at the indicated insertion point. You can also edit the replacement text if you wish.`n`nExample entry: :R:btw`::by the way,,,,,,,, :R: if ErrorLevel  ; The user pressed Cancel.

    return

IfInString, Hotstring, :R`:::

{

    MsgBox You didn't provide an abbreviation. The hotstring has not been added.
    return

}

; Otherwise, add the hotstring and reload the script:

FileAppend, `n%Hotstring%, %A_ScriptFullPath%  ; Put a `n at the beginning in case file lacks a blank line at its end.

Reload

Sleep 200 ; If successful, the reload will close this instance during the Sleep, so the line below will never be reached.

MsgBox, 4,, The hotstring just added appears to be improperly formatted.  Would you like to open the script for editing? Note that the bad hotstring is at the bottom of the script.
IfMsgBox, Yes, Edit

return

MoveCaret:

IfWinNotActive, New Hotstring

    return

; Otherwise, move the InputBox's insertion point to where the user will type the abbreviation.
Send {Home}{Right 3}

SetTimer, MoveCaret, Off

return


 

 


Version 1.1.30.00

https://autohotkey.com

©2003-2014 Chris Mallett, portions ©AutoIt Team and the AHK community

Software License: GNU General Public License
Quick Reference

Getting started:

How to use the program

Tutorial for beginners

Text editors with AutoHotkey support
Frequently asked questions

Scripts:

Concepts and conventions: explanations of various things you need to know.
Scripting language: how to write scripts.

Miscellaneous topics

Command and function list

Variables and expressions

Functions

Objects

Interactive debugging

Keyboard and mouse:

Hotkeys (mouse, joystick and keyboard shortcuts)

Hotstrings and auto-replace

Remapping keys and buttons

List of keys, mouse buttons and joystick controls

Other:

DllCall

RegEx quick reference

Script compatibility - AutoHotkey 1.0 users read this

Acknowledgements

A special thanks to Jonathan Bennett, whose generosity in releasing AutoIt v2 as free software in 1999 served as an inspiration and time- saver for myself and many others worldwide. In addition, many of AutoHotkey's enhancements to the AutoIt v2 command set, as well as the Window Spy and the old script compiler, were adapted directly from the AutoIt v3 source code. So thanks to Jon and the other

AutoIt authors for those as well.

Finally, AutoHotkey would not be what it is today without these other individuals.
~ Chris Mallett



 


List of Keys (Keyboard, Mouse and Joystick)

Table of Contents

Mouse

General Buttons
Advanced Buttons
Wheel

Keyboard

General Keys

Cursor Control Keys
Numpad Keys
Function Keys
Modifier Keys
Multimedia Keys
Other Keys

Joystick

Hand-held Remote Controls
Special Keys

Mouse

General Buttons

LButton                                   Left mouse button
RButton                                   Right mouse button
MButton                                  Middle or wheel mouse button

Advanced Buttons

XButton1                                 4th mouse button. Typically performs the same function as Browser_Back.
XButton2                                 5th mouse button. Typically performs the same function as Browser_Forward.

Wheel

WheelDown                             Turn the wheel downward (toward you).
WheelUp                                  Turn the wheel upward (away from you).

[v1.0.48+]: Scroll to the left or right.


WheelLeft WheelRight


Requires Windows Vista or later. These can be used as hotkeys with some (but not all) mice which have a second wheel or support tilting the wheel to either side. In some cases, software bundled with the mouse must instead be used to control this feature. Regardless of the particular mouse, Send and Click can be
used to scroll horizontally in programs which support it.


 

Keyboard

Note: The names of the letter and number keys are the same as that single letter or digit. For example: b is the B key and 5 is the 5 key. Although any single character can be used as a key name, its meaning (scan code or virtual keycode) depends on the current keyboard layout. Additionally, some special characters may need to be escaped or enclosed in braces, depending on the context. [v1.1.27+]: The letters a-z or A-Z can be used to refer to the corresponding virtual keycodes (usually vk41-vk5A) even if they are not included in the
current keyboard layout.

General Keys

CapsLock                                 CapsLock (caps lock key)
Space                                        Space (space bar)
Tab                                           Tab (tabulator key) 

Enter (or Return)                      Enter

Escape (or Esc)                        Esc

Backspace (or BS)                   Backspace


Cursor Control Keys

ScrollLock                                ScrollLock (scroll lock key)
Delete (or Del)                         Delete

Insert (or Ins)                           Insert
Home                                       Home
End                                          End
PgUp                                        PageUp (page up key)
PgDn                                        PageDown (page down key)
Up                                            (up arrow key)
Down                                       (down arrow key)
Left                                          (left arrow key)
Right                                        (right arrow key)

Numpad Keys

Due to system behavior, the following keys seperated by a slash are identified differently depending on whether NumLock is ON or OFF. If NumLock is OFF but Shift is pressed, the system temporarily releases Shift and acts as though NumLock is ON.

Numpad0 / NumpadIns           0 / Insert

Numpad1 / NumpadEnd          1 / End

Numpad2 / NumpadDown      2 /

Numpad3 / NumpadPgDn       3 / PageDown

Numpad4 / NumpadLeft         4 /

Numpad5 / NumpadClear        5 / typically does nothing
Numpad6 / NumpadRight       6 /

Numpad7 / NumpadHome       7 / Home

Numpad8 / NumpadUp           8 /

Numpad9 / NumpadPgUp       9 / PageUp

NumpadDot / NumpadDel       . / Delete
NumLock                                 NumLock (number lock key)
NumpadDiv                             / (division)
NumpadMult                           * (multiplication)
NumpadAdd                            + (addition)
NumpadSub                             - (subtraction)
NumpadEnter                          Enter

Function Keys

F1 - F24                                   The 12 or more function keys at the top of most keyboards.
Modifier Keys

LWin                                        Left Win. Corresponds to the <# hotkey prefix.

Right Win. Corresponds to the ># hotkey prefix.

Note: Unlike Control/Alt/Shift, there is no generic/neutral "Win" key because the OS does not support
it. However, hotkeys with the # modifier can be triggered by either Win key.

Control (or Ctrl)                       Control. As a hotkey (Control::) it fires upon release unless it has the tilde prefix. Corresponds to the ^
hotkey prefix.

Alt                                            Alt. As a hotkey (Alt::) it fires upon release unless it has the tilde prefix. Corresponds to the ! hotkey 
prefix.

Shift                                         Shift. As a hotkey (Shift::) it fires upon release unless it has the tilde prefix. Corresponds to the +
hotkey prefix.

LControl (or LCtrl)                  Left Control. Corresponds to the <^ hotkey prefix.
RControl (or RCtrl)                  Right Control. Corresponds to the >^ hotkey prefix.
LShift                                       Left Shift. Corresponds to the <+ hotkey prefix.
RShift                                      Right Shift. Corresponds to the >+ hotkey prefix.


LAlt                                         Left Alt. Corresponds to the <! hotkey prefix.

Right Alt. Corresponds to the >! hotkey prefix.


RAlt


Note: If your keyboard layout has AltGr instead of RAlt, you can probably use it as a hotkey prefix via <^>! as described here. In addition, LControl & RAlt:: would make AltGr itself into a hotkey.


 

Multimedia Keys

The function assigned to each of the keys listed below can be overridden by modifying the Windows registry. This table shows the
default function of each key on most versions of Windows.

Browser_Back                         Back
Browser_Forward                    Forward
Browser_Refresh                     Refresh
Browser_Stop                          Stop
Browser_Search                       Search
Browser_Favorites                   Favorites
Browser_Home                        Homepage
Volume_Mute                          Mute the volume
Volume_Down                        Lower the volume
Volume_Up                             Increase the volume
Media_Next                             Next Track
Media_Prev                              Previous Track
Media_Stop                             Stop
Media_Play_Pause                   Play/Pause
Launch_Mail                            Launch default e-mail program
Launch_Media                         Launch default media player
Launch_App1                          Launch My Computer
Launch_App2                          Launch Calculator

Other Keys

AppsKey                                  Menu. This is the key that invokes the right-click context menu.
PrintScreen                               PrintScreen

CtrlBreak                                 Ctrl+Break

Pause                                        Pause

Break                                        Break. Since this is synonymous with Pause, use ^CtrlBreak in hotkeys instead of ^Pause or ^Break.
Help                                         Help. This probably doesn't exist on most keyboards. It's usually not the same as F1.
Sleep                                        Sleep. Note that the sleep key on some keyboards might not work with this.
SCnnn                                      Specify for nnn the scan code of a key. Recognizes unusual keys not mentioned above. See Special Keys 

for details.

Specify for nn the hexadecimal virtual key code of a key. This rarely-used method also prevents certain types of hotkeys from requiring the keyboard hook. For example, the following hotkey does not use the keyboard hook, but as a side-effect it is triggered by pressing either Home or NumpadHome:

^VK24::MsgBox You pressed Home or NumpadHome while holding down Control.

Known limitation: VK hotkeys that are forced to use the keyboard hook, such as *VK24 or ~VK24, will


VKnn


fire for only one of the keys, not both (e.g. NumpadHome but not Home). For more information about the VKnn method, see Special Keys.

Warning: Only Send, GetKeyName, GetKeyVK, GetKeySC and #MenuMaskKey support combining
VKnn and SCnnn. [v1.1.27+]: The presence of an invalid suffix prevents VKnn from being recognized. For example, vk1Bsc001:: raises an error in v1.1.27+, but sc001 was ignored (had no effect) in previous versions.


 

Joystick

Joy1 through Joy32: The buttons of the joystick. To help determine the button numbers for your joystick, use this test script. Note that


hotkey prefix symbols such as ^ (control) and + (shift) are not supported (though GetKeyState can be used as a substitute). Also note that the pressing of joystick buttons always "passes through" to the active window if that window is designed to detect the pressing of

joystick buttons.

Although the following Joystick control names cannot be used as hotkeys, they can be used with GetKeyState:

JoyX, JoyY, and JoyZ: The X (horizontal), Y (vertical), and Z (altitude/depth) axes of the joystick.

JoyR: The rudder or 4th axis of the joystick. 

JoyU and JoyV: The 5th and 6th axes of the joystick. 

JoyPOV: The point-of-view (hat) control.

JoyName: The name of the joystick or its driver. 

JoyButtons: The number of buttons supported by the joystick (not always accurate). 

JoyAxes: The number of axes supported by the joystick.

JoyInfo: Provides a string consisting of zero or more of the following letters to indicate the joystick's capabilities: Z (has Z axis), R (has R axis), U (has U axis), V (has V axis), P (has POV control), D (the POV control has a limited number of discrete/distinct settings), C
(the POV control is continuous/fine). Example string: ZRUVPD

Multiple Joysticks: If the computer has more than one joystick and you want to use one beyond the first, include the joystick number
(max 16) in front of the control name. For example, 2joy1 is the second joystick's first button.

Note: If you have trouble getting a script to recognize your joystick, one person reported needing to specify a joystick number other than 1 even though only a single joystick was present. It is unclear how this situation arises or whether it is normal, but experimenting with
the joystick number in the joystick test script can help determine if this applies to your system.

See Also:

Joystick remapping: methods of sending keystrokes and mouse clicks with a joystick.
Joystick-To-Mouse script: using a joystick as a mouse.

Hand-held Remote Controls

Respond to signals from hand-held remote controls via the WinLIRC client script.
Special Keys

If your keyboard or mouse has a key not listed above, you might still be able to make it a hotkey by using the following steps:

1. Ensure that at least one script is running that is using the keyboard hook. You can tell if a script has the keyboard hook by opening

its main window and selecting "View->Key history" from the menu bar.

2. Double-click that script's tray icon to open its main window.

3. Press one of the "mystery keys" on your keyboard.

4. Select the menu item "View->Key history"

5. Scroll down to the bottom of the page. Somewhere near the bottom are the key-down and key-up events for your key. NOTE:

Some keys do not generate events and thus will not be visible here. If this is the case, you cannot directly make that particular key
a hotkey because your keyboard driver or hardware handles it at a level too low for AutoHotkey to access. For possible solutions,
see further below.

6. If your key is detectable, make a note of the 3-digit hexadecimal value in the second column of the list (e.g. 159).
7. To define this key as a hotkey, follow this example:

SC159:: ; Replace 159 with your key's value.
MsgBox, %A_ThisHotkey% was pressed.

return

Reverse direction: To remap some other key to become a "mystery key", follow this example:

; Replace 159 with the value discovered above. Replace FF (if needed) with the

; key's virtual key, which can be discovered in the first column of the Key History screen.
#c::Send {vkFFsc159}

Alternate solutions: If your key or mouse button is not detectable by the Key History screen, one of the following might help:

1. Reconfigure the software that came with your mouse or keyboard (sometimes accessible in the Control Panel or Start Menu) to

have the "mystery key" send some other keystroke. Such a keystroke can then be defined as a hotkey in a script. For example, if
you configure a mystery key to send Control+F1, you can then indirectly make that key as a hotkey by using ^F1:: in a script.

2. Try AHKHID. You can also try searching the forum for a keywords like RawInput*, USB HID or AHKHID.

3. The following is a last resort and generally should be attempted only in desperation. This is because the chance of success is low

and it may cause unwanted side-effects that are difficult to undo:

Disable or remove any extra software that came with your keyboard or mouse or change its driver to a more standard one such as
the one built into the OS. This assumes there is such a driver for your particular keyboard or mouse and that you can live without
the features provided by its custom driver and software.